LeetCode 167.两数之和Ⅱ 输入有序数组

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:

返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:

输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

解题思路

1.暴力打表,会超时

class Solution {
  public int[] twoSum(int[] numbers, int target) {
    for (int i = 0; i < numbers.length; i++) {
      for (int j = i + 1; j < numbers.length; j++) {
        if ((numbers[i] + numbers[j]) == target) {
          return new int[] {i+1, j+1};
        }
      }
    }
    throw new IllegalArgumentException("参数不存在!");
  }
}

2.双指针碰撞(官方解法)

class Solution {
  public int[] twoSum(int[] numbers, int target) {
    int left = 0;
    int right = numbers.length - 1;
    while (left < right) {
      if ((numbers[left] + numbers[right]) > target) {
        right--;
      } else if ((numbers[left] + numbers[right]) < target) {
        left++;
      } else {
        return new int[] {left + 1, right + 1};
      }
    }
    throw new RuntimeException("找不到参数");
  }
}

时间复杂度O(n),空间复杂度O(1)

3.二分法(来自评论),需要指定二分法起始查询位置,边界值的坑有点大

class Solution {
  public int[] twoSum(int[] numbers, int target) {
    for (int i = 0; i < numbers.length; i++) {
      //通过二分查找target-numbers[i]的位置,需要注意边界值
      //二分查找left起始位置应为i+1,否则对于测试用例[1, 2, 3, 4, 4, 9, 56, 90] 8,会出现返回[4,4]的情况
      int right = binarySearch(numbers, i + 1, numbers.length - 1, target - numbers[i]);
      if (right != -1) {
        return new int[] {i + 1, right + 1};
      }
    }
    throw new IllegalArgumentException();
  }

  public int binarySearch(int nums[], int left, int right, int target) {
    while (left <= right) {
      int mid = (left + right) / 2;
      if (nums[mid] == target) {
        return mid;
      } else if (nums[mid] < target) {
        left = mid + 1;
      } else {
        right = mid - 1;
      }
    }
    return -1;
  }
}

时间复杂度O(n^2),空间复杂度O(1)

posted @ 2019-08-25 21:08  lz_0011  阅读(102)  评论(0编辑  收藏  举报