LeetCode:0001.TwoSum

1. 描述

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

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

You can return the answer in any order.

Example 1:

Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums[1] == 9, we return [0, 1].

Example 2:

Input: nums = [3,2,4], target = 6
Output: [1,2]

Example 3:

Input: nums = [3,3], target = 6
Output: [0,1]

Constraints:

  • 2 <= nums.length <= 103
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • Only one valid answer exists.

2. 分析及实现

假设有一个数组 a=[2, 7, 11, 15],寻找和为 26 的两个元素的下标。

1. 暴力法

暴力法是最容易想到的解决方法,使用两个for循环分别取值相加,计算和是否为 26。此种方案的时间复杂度为 O(n2)

假设数组的 size 为 n,那么 最外层 i 的取值范围为 [0,n-1),内层 j 的取值范围为 [i+1, n-1]。

代码如下:

vector<int> twoSum(vector<int>& nums, int target) {
    size_t size_of_nums = nums.size();

    int i = 0, j = 0;
    for (; i < size_of_nums - 1; i++)
    {
        for (j = i + 1; j < size_of_nums; j++)
        {
            if (nums[i] + nums[j] == target)
            {
                return {i, j};
            }
        }
    }

    return {};
}
2. Hash 法

另一种解法是首先将数组的值都放到一个Hash Map里,数组的值作为 key 值,数组元素的下标作为 value 值;然后遍历数组去找与其对应对的另一元素是否存在 Map 中。这个解决方案的时间复杂度为 O(n)。

注意:遍历数组时 i 的取值范围为 [0, n-1),因为前面的数组元素都和最后一个元素进行了匹配。

代码如下:

vector<int> twoSumWithHash(vector<int>& nums, int target) {
    size_t size_of_nums = nums.size();

    unordered_map<int, int> mymap;
    for (int i = 0; i < size_of_nums; i++)
    {
        mymap[nums[i]] = i;
    }

    for (int i = 0; i < size_of_nums - 1; i++)
    {
        const int another = target - nums[i];
        if (mymap.find(another) != mymap.end() && mymap[another] > i)
        {
            return {i, mymap[another]};
        }
    }

    return {};
}
3. Hash 法改进

上述 Hash 解法需要遍历数组两次,其实可以只遍历一次,不需要一开始就建立好 Map,而是在后面遍历的过程中创建 Map。执行流程如下:

需要注意的是:最后返回两个下标要注意顺序,在 Map 中的元素下标是小于正在遍历的数组元素的下标。

代码如下:

vector<int> twoSumWithHash2(vector<int>& nums, int target) {
    unordered_map<int, int> mymap;
    for (int i = 0; i < nums.size(); i++)
    {
        const int another = target - nums[i];
        if (mymap.find(another) != mymap.end())
        {
            return {mymap[another], i};
        }
        mymap[nums[i]] = i;
    }
    return {};
}

3. 测试

使用 Catch2 进行测试,项目配置详见 github

#include "0001. Two Sum.h"
#include <catch2/catch_test_macros.hpp>

#include <iostream>

#include "../utils/utils.h"

using namespace std;

TEST_CASE("Two Sum", "[twoSum]")
{
    Solution solution;

    SECTION("1")
    {
        vector<int> expected_result{0, 1};
        vector<int> nums{2, 7, 11, 15};
        vector<int> result = solution.twoSum(nums, 9);
        REQUIRE(CompareVectors<int>(expected_result, result) == true);
    }
    SECTION("2")
    {
        vector<int> expected_result{1, 3};
        vector<int> nums{2, 7, 11, 15};
        vector<int> result = solution.twoSum(nums, 22);
        REQUIRE(CompareVectors<int>(expected_result, result) == true);
    }
}

TEST_CASE("Two Sum Hash", "[Two Sum Hash]")
{
    Solution solution;
    SECTION("1")
    {
        vector<int> expected_result{0, 1};
        vector<int> nums{2, 7, 11, 15};
        vector<int> result = solution.twoSumWithHash(nums, 9);
        REQUIRE(CompareVectors<int>(expected_result, result) == true);
    }
    SECTION("2")
    {
        vector<int> expected_result{1, 3};
        vector<int> nums{2, 7, 11, 15};
        vector<int> result = solution.twoSumWithHash(nums, 22);
        REQUIRE(CompareVectors<int>(expected_result, result) == true);
    }
}

TEST_CASE("Two Sum Hash2", "[Two Sum Hash2]")
{
    Solution solution;
    SECTION("1")
    {
        vector<int> expected_result{0, 1};
        vector<int> nums{2, 7, 11, 15};
        vector<int> result = solution.twoSumWithHash2(nums, 9);
        REQUIRE(CompareVectors<int>(expected_result, result) == true);
    }
    SECTION("2")
    {
        vector<int> expected_result{1, 3};
        vector<int> nums{2, 7, 11, 15};
        vector<int> result = solution.twoSumWithHash2(nums, 22);
        REQUIRE(CompareVectors<int>(expected_result, result) == true);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C与Python实战

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值