01 两数之和 two sum

01 two sum

1. 题目描述

在一个数组中找两个数,让这两个数的和等于目标值target。

要求:这两个数任意一个不可以重复使用 即a 不能再找a进行相加

2. 题解

2.1 解法一:暴力解法

思路:

  1. 用第一层循环遍历第一个数,用第二层循环遍历第二个数,由于不可以重复,所以取第一个数后面的那个数。

  2. 判断两个数的和是否等于目标值,如果等于,则返回两个数的下标,如果不等于,则进行下次循环判断

// brute solution
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        for (int i = 0; i < nums.size(); i++) {
            for (int j = i + 1; j < nums.size(); j++) {
                if (nums[i] + nums[j] == target) {
                    result.push_back(i);
                    result.push_back(j);
                    return result;
                }
            }
        }
        return result;
    }
};

算法复杂度: O ( n 2 ) O(n^2) O(n2)

2.2 哈希解法

思路:

改进暴力解法,那改进的想法是什么呢?那就是尽可能的寻找题目条件。这道题的隐藏条件是如果我找到第一个数a,那么第二数其实已经知道需要找什么了 即target - a

而知道找什么,就可以做改进。那怎么改呢? 提高找的效率,那最好是哈希了,因为算法复杂度是 O ( 1 ) O(1) O(1) ,所以第二个数可以通过构建哈希表来实现第二个数的命中


正常思路是先将数组中的数进行哈希映射,即哈希的key是数组中的值value 而value是值的index,因为最后返回的是index

然后再去遍历,但是要避免重复。比如: 3,3 这个数组, target是6

先去构造哈希:

3 -> 0

3 -> 1

当a取3的时候,要找的第二个值b= 6-3 = 3 这时候就存在重复,因为命中的index是0 ,而题目要求是不可以重复元素的

所以需要加一个判断条件,即b的下标不等于a的下标

class Solution{
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> result;
        unordered_map<int, int> table; // key : value value : index
        // generate a hashtable
        for (int i = 0; i < nums.size(); i++) {
            table[nums[i]] = i;
        }
        for (int i = 0; i < nums.size(); i++) {
            int a = nums[i];
            int find_value = target - a;
            auto re = table.find(find_value);
            if (re!=table.end()) { // find it
                if (re->second == i) {
                    continue;
                }
                result.push_back(i);
                result.push_back(re->second);
                return result;
            }
        }
        return result;
    }
};

算法复杂度: O ( n ) O(n) O(n)

2.3 解法三:一个小技巧

如何优化重复元这个写法?

采用了边遍历边构建的方式进行构造哈希表

class Solution{
public:
    vector<int> twoSum(vector<int> &numbers, int target){
        //Key is the number and value is its index in the vector.
        unordered_map<int, int> hash;
        vector<int> result;
        for (int i = 0; i < numbers.size(); i++) {
            int numberToFind = target - numbers[i];
            auto re = hash.find(numberToFind);
            if (re != hash.end()) {
                result.push_back(i);
                result.push_back(re->second);
                return result;
            }
            //number was not found. Put it in the map.
            hash[numbers[i]] = i;
        }
        return result;
    }
};

算法复杂度: O ( n ) O(n) O(n)

3. 视频讲解

[LeetCode] 01-two sum

4. 总结

  1. c++中使用unordered_map来做哈希
  2. 哈希的构造可以边遍历边构造
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值