1. 程式人生 > >Leetcode每日一道 -- 兩數之和

Leetcode每日一道 -- 兩數之和

題目連結:  https://leetcode-cn.com/problems/two-sum/description/

題目描述: 

給定一個整數陣列 nums 和一個目標值 target,請你在該陣列中找出和為目標值的 兩個 整數。

你可以假設每種輸入只會對應一個答案。但是,你不能重複利用這個陣列中同樣的元素。

示例:

給定 nums = [2, 7, 11, 15], target = 9

因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

題目分析 : 最直觀想法是暴力搜尋,複雜度是O(N^2),但是這樣是不過的。還有一種方式是排序之後,利用雙指標方法進行搜尋,複雜度是O(n*lgn),依然很複雜。比較理想的想法是看到一個數字能夠快速找到 target-nums[i] 是否在陣列中,本質上是一個檢索問題,最快的查詢方式就是利用Hash對映查詢。Python中的set是基於Hash對映進行查詢的,在C++中unorder_map是基於Hash對映進行查詢的。程式碼如下:

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        nums_set=set(nums) #將nums轉為集合
        for i in range(0,len(nums)):
            if (target-nums[i]) in nums_set: #判斷是否nums[i]的補數在集合中
                low=i
                for j in range(i+1,len(nums)): #上面判斷出了nums[i]的補數在集合中,需要查詢下標
                    if nums[j]+nums[i]==target:
                        return [i,j]

C++程式碼如下: 宣告C++我沒有和python一樣用 集合 進行查詢是因為c++的set是基於紅黑樹的查詢方式,查詢的效率是O(logn)

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> d;
        int len=nums.size();
        vector<int> res;
        for(int i=0;i<len;i++)
        {
            if(d.count(target-nums[i])) //判斷target-nums[i]是否在d的key值列表中
            {
                res.push_back(d[target-nums[i]]);
                res.push_back(i);
                return res;
            }
            else
            {
                d[nums[i]]=i; 
            }
        }
    }
};

知識點總結:

(1). Python 的set型別和C++的unordered_map是由Hash對映實現的,查詢效率是O(n)。 C++的map和set是基於紅黑樹的,查詢速度是O(logn)。

(2).記住一個API:

ordered_map<int,int> d: //宣告一個無序對映

d[i]=j; //對i 鍵值賦值

d.count(i)!=0  d.find(i) != d.end()   //在d的鍵值中查詢i是否存在