力扣1 two sum
一.如果数组中的元素值是从小到大有序排列,那么可以利用数组有序来解决问题。
1.left 指向数组中的第一个元素,right 指向数组中的最后一个元素。
2.如果 nums[left] + nums[right] 大于 target 时,可以将 right 左移,使得 nums[left]+nums[right] 的值减小,然后再看两数之和与 target 的大小.
3.如果 nums[left] + nums[right] 小于 target 时,可以将 left 向右移,增大两数之和。反复的移动 left 和 right
4.最终的循环结束条件是 left == right。
class Solution { public int[] twoSum(int[] nums, int target) { if(nums == null || nums.length == 0) return new int[2]; int left = 0; int right = nums.length-1; while(left < right){ if(nums[left] + nums[right] > target){ right--; } if(nums[left] + nums[right] < target){ left++; } if(nums[left] + nums[right] == target){ return new int[]{left,right}; } } return new int[2]; } }
但是在力扣中不能用这个方式刷题,因为题目没有指明说数组有序,如果取一个无序数组就失败了。如果使用Arrays.sort(nums)来对数组排序,还不能通过,失败的原因是sort函数改变了数组本身,导致数组的索引发生变化,而且在数组处理之前加一个数组排序,会增大时间复杂度,sort 的时间复杂度是nlogn。
二.暴力解法。时间复杂度O(n^2)
class Solution { public int[] twoSum(int[] nums, int target) { int a[] = new int[2]; for(int i = 0;i < nums.length;i++){ for(int j = i + 1;j < nums.length;j++){ if(nums[i] + nums[j] == target){ a[0] = i; a[1] = j; return a; } } } return a; } }
3.HashMap HashMap的查找时间复杂度是O(1)
以 nums=[3,2,7,5] target = 8为例
1.从0号索引开始 , nums[0] = 3 , target - nums[0] = 5 在Map中找5,没有5的化就放弃nums[0] , 把num[0]的值和索引放在Map中。
2.指到nums[1]=2,然后再Map中找6,没有6,就把nums[1]的值和索引放在Map中.
3.指向nums[2],在Map中找1,没有1,将nums[2]的值和索引放在Map中。
4.指向nums[3],在Map中找3,Map中有3,将值为3和5的下标放在一个数组中,将数组返回。
class Solution { public int[] twoSum(int[] nums, int target) { int desired; Map<Integer,Integer> map = new HashMap<>();//元素值 索引 for(int i = 0;i < nums.length;i++){ desired = target - nums[i]; if(map.containsKey(desired)){ return new int[] {map.get(desired),i}; } else { map.put(nums[i],i); } } return new int[2]; } }