1. 程式人生 > >LeetCode:兩數之和、三數之和、最接近的三數之和

LeetCode:兩數之和、三數之和、最接近的三數之和

都用雜湊表的方法

兩數之和

vector<int> twoSum(vector<int>& nums, int target) {
        int s;
        unordered_map<int,int> map;
        for(int k = 0; k < nums.size();k++)
        {
            map[nums[k]] = k;
        }
        
        for(int i = 0; i < nums.size(); i++)
        {
            s = target - nums[i];
            if(map.count(s) != 0 && map[s] != i)
                return {i,map[s]};
        }
    }

利用unordered_map儲存nums的雜湊對映關係,map利用陣列的方式儲存,相同關鍵字衝突時,後者可以覆蓋前者。

遍歷時利用target-nums[i]找到對應地址。

unordered_map和map的區別

map:

  1. 優點: 
    1. 有序性,這是map結構最大的優點,其元素的有序性在很多應用中都會簡化很多的操作
    2. 紅黑樹,內部實現一個紅黑書使得map的很多操作在lgn的時間複雜度下就可以實現,因此效率非常的高
  2. 缺點: 空間佔用率高,因為map內部實現了紅黑樹,雖然提高了執行效率,但是因為每一個節點都需要額外儲存父節點、孩子節點和紅/黑性質,使得每一個節點都佔用大量的空間

  3. 適用處:對於那些有順序要求的問題,用map會更高效一些

unordered_map:

  1. 優點: 因為內部實現了雜湊表,因此其查詢速度非常的快
  2. 缺點: 雜湊表的建立比較耗費時間
  3. 適用處:對於查詢問題,unordered_map會更加高效一些,因此遇到查詢問題,常會考慮一下用unordered_map

總結:  1. 記憶體佔有率的問題就轉化成紅黑樹 VS hash表 , 還是unorder_map佔用的記憶體要高。  2. 但是unordered_map執行效率要比map高很多  3. 對於unordered_mapunordered_set容器,其遍歷順序與建立該容器時輸入的順序不一定相同,因為遍歷是按照雜湊表從前往後依次遍歷的

三數之和

vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> Sum;
        sort(nums.begin(),nums.end());
        if(nums.empty() || nums[0] > 0 || nums.back() < 0)
            return {};
        for(int i = 0; i < nums.size(); i++)
        {
            if(nums[i] > 0)
                break;
            if(i > 0 && nums[i] == nums[i-1])
                continue;
            int m = i+1, n = nums.size()-1;//m = i.next; n = nums.final
            while(m < n)
            {
                if(nums[m] + nums[n] + nums[i] ==0)
                {
                    Sum.push_back({nums[i], nums[m], nums[n]});
                    m++;
                    n--;
                    while(m < n && nums[m] == nums [m-1])
                        m++;
                    while(m < n && nums[n] == nums[n+1])
                        n--;
                }
                else if(nums[m] + nums[n] + nums[i] > 0)
                    n--;
                else
                    m++;
            }
        }
        return Sum;
        
    }

先將nums排序,建立雜湊表

確定一個值,尋找另外兩個值時,從最近和最遠逐步向中間靠攏,越靠近頭部越小,越靠近尾部越大。

最接近的三數之和

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        int k,sum,m,n;
        sort(nums.begin(),nums.end());
        
        k = nums[0] + nums[1] + nums[nums.size() - 1];
        for(int i = 0; i < nums.size(); i++)
        {
            m = i + 1;
            n = nums.size() - 1;
            while(m < n)
            {
                sum = nums[i] + nums[m] + nums[n];
                if(abs(k - target) >= abs(sum - target))
                {
                    k = sum;
                }
                if(sum < target)
                    m++;
                else if(sum > target)
                    n--;
                else
                    return k;
            }
        }
        
        
        return k;
    }
};