1. 程式人生 > >leetcode 1: twosum

leetcode 1: twosum

題目描述:給出一個int陣列和一個int目標值,在陣列中找兩數之和等於target。假設肯定能找且每個數只能用一次。返回兩數在陣列的下標。

方法一:暴力求解

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        for(int i=0;i<nums.size();i++){
            for(int j=i+1;j<nums.size();j++){
                if(nums[i]+nums[j]==target)
                    return vector<int>{i,j};//多借鑑這種返回vector的方法 
            }
        }
        return vector<int>{-1,-1}; 
    }
};

不足:時間複雜度是o(n^2

優點:思路清晰、簡單

方法二:藉助 unordered_map

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
       if(nums.size()<=1) return vector<int>{-1,-1};
        unordered_map<int,int> hash;
        for(int i=0;i<nums.size();i++){
            hash[nums[i]]=i;
        }
        for(int j=0;j<nums.size();j++){
            if(hash.find(target-nums[j])!=hash.end() && hash[target-nums[j]]!=j){//每個元素只能用一次
                return vector<int>{j,hash[target-nums[j]]};
            } 
        }
        return vector<int>{-1,-1};
    }
};

改進編碼版:

少了一層迴圈,不必先全部插入hash,而是一邊判斷,一邊插入。因為兩數和具有交換等效性,通過前面的數找不到,後面找也是等價的,並不會漏掉!

很值得借鑑!!!!!!!!!!!!!

class Solution {
public:
      vector<int> twoSum(vector<int>& nums, int target) {
       if(nums.size()<=1) return vector<int>{-1,-1};
          unordered_map<int, int> hash;
    
        for (int i = 0;i<nums.size(); ++i) {
             auto it = hash.find(target - nums[i]);
             if (it != hash.end()) 
                return vector<int> {i, it->second};   //此處不擔心使用重複元素,因為判斷時元素還未插入
            hash[nums[i]] = i;
        }
       return vector<int>{-1,-1};   
   }
};

不足:前提要求陣列中沒有相同元素

優點:時間複雜度o(n)

拓展:先排序,兩個指標分別從兩端向中間收攏。但是隻能判斷能否the sum  of 2 nums equals target,因為排序會打亂下標。