167.两数之和 II - 输入有序数组

 给定一个已按照 升序排列  的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。

函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。


示例 1:

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

方法一:参考题目两数之和,使用暴力法or哈希表,但未用到数组升序排列的优势

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        map<int, int> mapNums;
        for(int i = 0; i < numbers.size(); i++) {
            if(mapNums.count(target-numbers[i]) == 1) 
               return {mapNums[target-numbers[i]]+1, i+1};
            else
               mapNums[numbers[i]] = i;
        }
        return {0,0};
    }
};

错误记录:for判断时加了条件numbers[i]<target,本意是若数组值大于target的话就结束循环,提高效率,但未考虑数组中存在负数的情况,target比数组元素小的情况。

下标从1开始计数不等于从numbers[1]开始存放数据。

方法二:二分查找法

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        for(int i = 0; i < numbers.size(); i++) {
            int low = i+1, high = numbers.size()-1;     //在numbers[i]的右边查找

            while(low <= high) {                       
                int mid = (high-low)/2 + low;
                if(numbers[mid] == target - numbers[i])  //找到
                   return {i+1, mid+1};
                //中间值比结果值小,继续在右半边查找,重置low,high不需要
                else if(numbers[mid] < target - numbers[i])  
                   low = mid+1;
                else                 //中间值比结果值大,则在左半边查找
                   high = mid-1;
            }
        }
        return {-1,-1};
    }
};

时间复杂度:O(nlogn)其中n是数组的长度。需要遍历数组一次确定第一个数,时间复杂度是 O(n),寻找第二个数使用二分查找,时间复杂度是 O(logn),因此总时间复杂度是 O(nlogn)。

空间复杂度:O(1)。

算法知识

二分查找:一种在有序数组中查找某一特定元素的搜索算法,每次比较都使搜索范围缩小一半。

搜索过程从数组的中间元素开始,若中间元素正好是要查找的元素,则搜索过程结束;若查找元素小于中间元素,则在数组左半边查找;若查找元素大于中间元素,则在数组右半边查找。如此反复,知道数组为空,则代表找不到。

方法三:双指针

数组首尾设置两个标志low和high,判断numbers[low]+numbers[high]是否等于target,若相等则返回;若小于target,此时high在最高位,数组有序,说明numbers[high]已经是最大值,若要增加numbers[low]+numbers[high]的和,只能增加numbers[low],因此low++进行判断;同理若大于target,此时要减少sum,因此high--。leetcode解题法有大神详细图解了这种缩减搜索空间的思路。

https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/solution/yi-zhang-tu-gao-su-ni-on-de-shuang-zhi-zhen-jie-fa/

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        int low = 0, high = numbers.size()-1;

        while(low < high) {
            int sum = numbers[low] + numbers[high];
            if(sum == target)
              return {low+1, high+1};
            else if(sum < target)
              low++;
            else
              high--;
        }
        return {-1,-1};
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值