[Leetcode] 167. Two Sum II - Input array is sorted 解题报告

本文介绍了一种在已排序数组中寻找两数之和等于特定目标值的方法。提出两种解决方案:朴素版采用双指针法,时间复杂度为O(n);改进版结合二分查找,将时间复杂度降至O(logn)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution and you may not use the same element twice.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

思路

建议将这道题目和Two Sum I这道题目结合起来学习。

1、朴素版:最朴素的思路仍然是采用two pointers来实现:初始化两个指针为数组的两端,然后判断他们的和,如果和大于target,则左移右端指针;如果和小于target,则右移左端指针,直到找到和正好等于target或者左右指针相遇。可是这种思路的时间复杂度还是O(n)。

2、改进版:通过分析朴素版我发现,其实每次只将指针移动一位比较保守,没有充分利用数组有序的特点。所以在改进版中,当和大于target的时候,我直接在数组中搜索target - numbers[left]的位置,并且据此更新右端指针;当和小于target的时候,直接在数组中搜索target - numbers[right]的位置,并据此更新左端指针。这样就可以将时间复杂度进一步降低到O(logn)。

代码

1、朴素版:

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        if (numbers.size() == 0) {
            return {};
        }
        int left = 0, right = numbers.size() - 1;
        while (left < right) {
            int val = numbers[left] + numbers[right];
            if (val == target) {
                return vector<int>{left + 1, right + 1};
            }
            else if (val > target) {
                --right;
            }
            else {
                ++left;
            }
        }
        return {};
    }
};

2、改进版:

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        if (numbers.size() == 0) {
            return {};
        }
        int left = 0, right = numbers.size() - 1;
        while (left < right) {
            int val = numbers[left] + numbers[right];
            if (val == target) {
                return vector<int>{left + 1, right + 1};
            }
            else if (val > target) {
                right = binarySearch(numbers, left + 1, right - 1, target - numbers[left]);
            }
            else {
                left = binarySearch(numbers, left + 1, right - 1, target - numbers[right]);
            }
        }
        return {};
    }
private:
    int binarySearch(vector<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) {
                end = mid - 1;
            }
            else {
                start = mid + 1;
            }
        }
        return start;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值