Two Sum - LeetCode 题解

1.Two Sum

Given an array of integers, return indices of the two numbers such that they add up to a specific target.

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

Example:

Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

首先,第一种做法就是用暴力枚举,在C++下可以通过,O(1)时间复杂度,但是两层循环枚举给他带来O(N^2)的空间复杂度,代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        /*暴力枚举*/
        for(int i = 0; i < nums.size() - 1; i++){
            for(int j = i + 1; j < nums.size(); j++){
                if(nums[i] + nums[j] == target){
                    return {i, j};
                }
            }
        }
        
        return {-1, -1};
    }
};

第二种,采用hash映射,用空间换时间,降低空间复杂度。想到用数组下标映射(桶),将数组的下标为该vector元素的值,数组元素的值为该vector元素的下标,这样就可以通过数组随机访问的性质得到vector元素的值及其在vector当中下标的映射。这种做法很巧妙,在并查集中也有应用。但是其缺点是,由于数组下标与元素的值相等,元素要非负数,否则就无法和非负的数组下标一一对应;元素的范围就是下标的范围,所以一旦vector中最大元素达到1000000,就要4MB的空间,再多点甚至会产生溢出,所以在这里也不适合。

第三种,采用STL自带的hash map,建立一个关于vector元素的值和vector元素下标的映射,接着顺序遍历vector元素,判断vector中是否有目标映射,他的键加上该元素等于目标和,则取出该元素的下标和该键值对的值就是能满足该和的下标。PS.注意如果目标和是当前元素的两倍,那么在hashmap中也可以找到该元素代码如下:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        /*两遍hash*/
        map<int, int> rec;
        
        // Add hash relations  
        for(int i = 0; i < nums.size(); i++){
            rec[nums[i]] = i;
        }
        
        // Search for coordinate record
        for(int i = 0; i < nums.size(); i++){
            if(rec.count(target - nums[i])){
                int index = rec[target - nums[i]];
                
                if(index != i){ // When the target isn't two times of the element
                    return {i, index};
                }
            }
        }
        
        return {-1, -1};
    }
};

第四种,其实只需要一遍hash

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        /*一遍哈希*/
        map<int, int> rec;
        int l, r;
        
        for(l = nums.size() - 1; l >= 0; l--){
            if(rec.count(target - nums[l])){
                r = rec[target - nums[l]];
                
                if(r != l){
                    break;
                }
            }
            
            rec[nums[l]] = l;
        }
        
        return {l, r};
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值