image.png

解题思路

二分解法

  1. 依次遍历每一个数据,numbers[i]。
  2. 对于每一个numbers[i],都在后面的有序数组中寻找target-numbers[i].
  3. 这里的寻找方法使用二分搜索法
  4. 如果找到直接返回,否则继续遍历下一个数据
  5. 时间复杂度O(nlogn)

image.png

  1. class Solution {
  2. public int[] twoSum(int[] numbers, int target) {
  3. int n = numbers.length;
  4. for(int i=0;i<n;i++){
  5. int remain = target-numbers[i];
  6. //返回二分查找法后的结果
  7. int search = binarySearch(numbers, i+1, remain);
  8. //没有解则继续 有解则返回答案
  9. if(search==-1)
  10. continue;
  11. else
  12. return new int[]{i+1,search+1};
  13. }
  14. return null;
  15. }
  16. //二分查找法 输入的是二分查找法的下标
  17. public int binarySearch(int[] nums,int begin,int target){
  18. //在【l,r】左闭右闭的区间内进行二分查找法
  19. int l=begin;
  20. int r=nums.length-1;
  21. while(l<=r){
  22. int mid = (l+r)/2;
  23. if(nums[mid]==target){
  24. return mid;
  25. }
  26. if(nums[mid]<target){
  27. l=mid+1;
  28. }
  29. else{
  30. r=mid-1;
  31. }
  32. }
  33. return -1;
  34. }
  35. }
  36. // time O(n*log(n))

对撞指针

目标是要寻找两个索引,一左一右存在。

  1. 初始化选择最左侧数字i,最右侧数字j
  2. 判断nums[i]+nums[j]==target
  3. 如果相等直接返回下标
  4. 如果>target说明 需要使整体的值变小才可能相等
  5. 又因为是有序数组,所以应该将j降低,j—
  6. 如果<target说明 需要使整体的值变大才可能相等
  7. 又因为是有序数组,所以应该将i增大,i++
  8. 直到i==j跳出循环

image.png
image.png
image.png

public int[] twoSum(int[] numbers, int target) {
        if(numbers==null||numbers.length<2)
            return null;
        //l,r表示左右两个指针,最开始分别在两端
        int l = 0;
        int r = numbers.length-1;
        //循环结束的条件是l==r 指针撞在了一起
        while(l<r){
            //找到直接返回
            if(numbers[l]+numbers[r]==target)
                return new int[]{l+1,r+1};
            //和大于target 调小r
            if(numbers[l]+numbers[r]>target)
                r--;
            //和小于target 调大l
            else
                l++;
        }
        return null;
    }