1.Two Sum

Description

   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].
题目传送门

一.题目理解

   这是LeetCode的第一道题目,LeetCode和之前刷的OJ有些不同,不用完全提交程序(包含main函数),是侧重算法的,我们只需要完成算法就好。
   下面说题目:这道题很好理解,给定一个数组,里面有很多整数,然后给定一个目标值,题目假设数组中刚好有两个数字之和等于目标值,我们需要找到这两个数字,并返回其下标。

二.题目解答

1.暴力求解

1.1 思路和代码

首先能想到的就是暴力求解,这种方法很简单,但是效率不高。

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

   

1.2 复杂度分析

  • 时间复杂度:O(n2) .对每一个元素,我们都要搜索剩余元素中有无匹配元素(两者之和为目标值),每一个元素花费的时间为O(n),总的时间为 O(n2).
  • 空间复杂度:O(1).

1.3 效果

image

2.优化

    这里的优化主要是根据Solution的指导而来,有两种优化Two-pass Hash Table, One-pass Hash Table。

2.1 Two-pass Hash Table

2.1.1 思路和代码

    为了降低时间复杂度,我们应该采用一个更合理的方式去进行匹配元素的搜索,由题目我们可以知道匹配元素一定存在且唯一,同时要求返回匹配元素的下标;考虑到匹配元素和其下标的匹配,自然联想到Hash表。
    通过哈希表我们可以把搜索一个元素的匹配元素的花费由O(n)降为O(1),不过代价是增加了空间开销,我们需要存储哈希表。尽管哈希表在有碰撞的情况下搜索花费能达到O(n),但是本题目刚好是有唯一解,这也就表示碰撞不会发生,因而我们可以大胆采用哈希表。
    由于匹配元素是唯一的,所以我们可以考虑无序表unorderded_map,使用元素的具体值作为键值,其下标作为映射值。
//Two-pass Hash Table
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {

        unordered_map<int,int> m;
        vector<int> ret;

        for(int i = 0; i < nums.size(); i++)
            m[nums[i]] = i;

        for(int i = 0; i < nums.size(); i++) {
            int complement = target - nums[i];

            if(m.count(complement) && m[complement] != i) {
                ret.push_back(i);
                ret.push_back(m[complement]);
                break;
            }
        }
        return ret;
    }
};

2.1.2 复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

2.1.3 效果

image

2.2 One-pass Hash Table

2.2.1 思路和代码

   上述的结果证明我们的思路是正确的,其实我们还可以继续优化,可以在生成哈希表的过程进行搜索,从而进一步提高速度,降低时间复杂度。

//One-pass Hash Table
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {

        unordered_map<int,int> m;
        vector<int> ret;

        for(int i = 0;i < nums.size();i++){

            if(m.count(target - nums[i])){
                ret.push_back(i);
                ret.push_back(m[target-nums[i]]);
                return ret;
            }
            m[nums[i]] = i;

        }
        
    }
};

2.2.2 复杂度分析

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

2.2.3 效果

image





















原文地址:https://www.cnblogs.com/ovs98/p/9830579.html