LeetCode167. 两数之和 | 刷题打卡

110 阅读1分钟

LeetCode从低效到高效,点击

一、题目描述:

题目要求

给定一个已按照 升序排列  的整数数组 numbers ,请你从数组中找出两个数满足相加之和等于目标数 target 。函数应该以长度为 2 的整数数组的形式返回这两个数的下标值。numbers 的下标 从 1 开始计数 ,所以答案数组应当满足 1 <= answer[0] < answer[1] <= numbers.length 。你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

来源:力扣(LeetCode)链接

示例

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

二、思路分析:

本题是一道比较简单的题,但是可以从这道题延伸出双指针的思路,以及哈希表的思路.由于已经有序,所以是优先用双指针来做的,左右指针分别指向数组左右,向中心搜索,直到找到合适的解.在使用字典时注意先判断,然后再加入,防止把把自己多算了一个.

三、AC 代码:

双指针思路

vector<int> twoSum_v1(vector<int> &numbers, int target)
{
    auto l = numbers.begin();
    auto r = numbers.end() - 1;
    while (l != r)
    {
        // 超过预期,说明右面的值没人配合,右指针左移
        if (*l + *r > target)
        {
            r--;
        }
        // 同理,左指针右移
        else if (*l + *r < target)
        {
            l++;
        }
        else
        {
            return vector<int>{int(distance(numbers.begin(), l)) + 1, int(distance(numbers.begin(), r)) + 1};
        }
    }
    return {};
}

但是,上述代码还有优化空间,可以复用一些变量,最终优化成下面这样

vector<int> twoSum(vector<int> &numbers, int target)
{
    unordered_map<int, int> m{};
    for (int i = 0; i < numbers.size(); i++)
    {
        if (m.find(target - numbers[i]) != m.end())
        {
            return {m[target - numbers[i]] + 1, i + 1};
        }
        // 这里之所以先判断,再加入本次元素,是为了防止本次扫描的元素*2==target
        else
        {
            m[numbers[i]] = i;
        }
    }
    return {};
}

四、总结:

本题是双指针解法的开始,使用双指针还有很多题目,从这道题开始也逐渐发现精巧的解法并不唯一,要根据实际选择合适的解法.

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情