Leetcode 167. 两数之和 II - 输入有序数组 Java&Python

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

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

说明:

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

示例:

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

在这里想和大家分享一下基本的解题思路,诚然这道题目非常简单,但是当遇到难题的时候,一个好的解题思路或许会为我们找到突破点。这道题用暴力解法,两次循环便可得出答案,但是提交给leetcode应该会timeout,因为O(n2)基本的算法在数据量太大的时候,会非常耗时,那么怎么降低时间复杂度呢,结合题目,我们可以看到数组是有序,既然是有序的数组,是否可以用二分查找来寻找target-number[i]呢?

public int[] twoSum(int[] numbers, int target) {

        int[] res = new int[2];

        for (int i = 0; i < numbers.length; i++) {
            int pos = findIndex(numbers, i + 1, numbers.length - 1, target - numbers[i]);
            if (pos >= 0) {
                res[0] = i + 1;
                res[1] = pos + 1;
            }
        }

        return res;
    }

    private int findIndex(int[] numbers, int start, int end, int target) {
        while (start <= end) {

            int mid = start + (end - start) / 2;

            if (numbers[mid] == target) {
                return mid;
            } else if (numbers[mid] < target) {
                start = mid + 1;
            } else {
                end = mid - 1;
            }
        }
        return -1;
    }

这样降到O(nlogn)便可以AC了,那么还有更好的解决方案吗,在遍历一次的情况下,便可以得到结果,这里可以使用对撞指针来解决,分别使两个指针指向首尾,如果相加等于,便找到了对应的索引,如果小于需要右移左指针,大于便左移右指针。

public int[] twoSum(int[] numbers, int target) {

        int l = 0, r = numbers.length - 1;

        while (l < r) {
            if (numbers[l] + numbers[r] == target) {
                return new int[]{l + 1, r + 1};
            } else if (numbers[l] + numbers[r] < target) {
                l++;
            } else {
                r--;
            }
        }

        return new int[2];
    }

下面是Python实现

class Solution:
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        i = 0
        j = len(numbers) - 1

        while i < j:
            if numbers[i] + numbers[j] == target:
                return [i + 1, j + 1]
            elif numbers[i] + numbers[j] < target:
                i += 1
            else:
                j -= 1

关于对撞指针,类似的题目还有Leetcode125号问题:验证回文串, 345号问题 反转字符串中的元音字母等,有兴趣的同学也可以做做这些题目。

猜你喜欢

转载自blog.csdn.net/sinat_33150417/article/details/82982637