不过我们采用双指针的方法,从数组的头尾两边向中间夹击的方法来做的话,时间复杂度仅需为 O(n),而且代码也会更加简洁,这里我给出代码吧,代码如下:
public int[] twoSum1(int[] nums, int target) { int[] res = new int[2]; int start = 0; int end = nums.length - 1; while(end > start){ if(nums[start] + nums[end] > target){ end--; }else if(nums[start] + nums[end] < target){ start ++; }else{ res[0] = start; res[1] = end; return res; } } return res; }这个例子相对比较简单,不过这个头尾双指针的方法,真的用的挺多的。
3、a ^ b ^ b = a 的应用两个相同的数异或之后的结果是 0,而任意数和 0 进行异或的结果是它本身,利用这个特性,也是可以解决挺多题,我在 leetcode 碰到过好几道,这里我举一些例子。
(1)数组中,只有一个数出现一次,剩下都出现两次,找出出现一次的数
这道题可能很多人会用一个哈希表来存储,每次存储的时候,记录 某个数出现的次数,最后再遍历哈希表,看看哪个数只出现了一次。这种方法的时间复杂度为 O(n),空间复杂度也为 O(n)了。
我们刚才说过,两个相同的数异或的结果是 0,一个数和 0 异或的结果是它本身,所以我们把这一组整型全部异或一下,例如这组数据是:1, 2, 3, 4, 5, 1, 2, 3, 4。其中 5 只出现了一次,其他都出现了两次,把他们全部异或一下,结果如下:
由于异或支持交换律和结合律,所以:
1^2^3^4^5^1^2^3^4 = (1^1)^(2^2)^(3^3)^(4^4)^5= 0^0^0^0^5 = 5。
通过这种方法,可以把空间复杂度降低到 O(1),而时间复杂度不变,相应的黛米如下
int find(int[] arr){ int tmp = arr[0]; for(int i = 1;i < arr.length; i++){ tmp = tmp ^ arr[i]; } return tmp; } 总结这阵子由于自己也忙着复习,所以并没有找太多的例子,上面的那些题,有些在之前的文章也是有写过,这里可以给那些看过的忘了的复习一些,并且也考虑到可能还有一大部分人没看过。
所以呢,希望看完这篇文章,以后遇到某些题,可以多一点思路,如果你能用上这些技巧,那肯定可以大大降低问题的难度。
如果你觉得这篇内容对你挺有启发,为了让更多的人看到这篇文章:不妨
1、点赞,让更多的人也能看到这篇内容
2、关注公众号「苦逼的码农」,主要写算法、计算机基础之类的文章,里面已有100多篇原创文章
大部分的数据结构与算法文章被各种公众号转载相信一定能让你有所收获