查找表,Two Sum,15. 3Sum,18. 4Sum

解法一:排序后使用双索引对撞:O(nlogn)+O(n) = O(nlogn) , 但是返回的是排序前的指针。

解法二:查找表。将所有元素放入查找表, 之后对于每一个元素a,查找 target-a 是否存在。使用map实现,键是元素的值,键值是元素对应的索引。

不能把vector中所有的值放到查找表中,因为若有重复的值,前一个会被后一个覆盖。所以改善为把当前元素v前面的元素放到查找表中。

时间复杂度:O(n)

空间复杂度:O(n)

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> record;
        for(int i=0; i<nums.size();i++){
            int complement = target - nums[i];
            if(record.find(complement) != record.end()){
                int res[2] = {i, record[complement]};  //res记录两个元素的索引
                return vector<int>(res, res+2);
            }
            record[nums[i]] = i;
        }
        throw invalid_argument("The input has no solution");
    }
};

需要考虑不同的三元组:是要求值不同还是索引不同。

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int> > res;
        if(nums.size()<=2){
            return res;
        }
        
        sort(nums.begin(), nums.end());
        size_t i = 0;
        while(i<nums.size()-2){
            int target = -nums[i];
            int l = i+1;
            int r = nums.size()-1;
            while(l<r){
                int sum = nums[l]+nums[r];
                if(sum<target)
                    l++;
                else if(sum>target)
                    r--;
                else{
                    vector<int> triplet = {nums[i], nums[l], nums[r]};
                    res.push_back(triplet);
                    //避免把重复的一组数字存入res中
                    while(l<r && nums[l] == triplet[1])
                        l++;
                    while(l<r && nums[r] == triplet[2])
                        r--;
                }
            }
            int curNum = nums[i];
            while(i<nums.size()-2 && nums[i]==curNum)
                i++;
        }
        return res;
    }
};

猜你喜欢

转载自www.cnblogs.com/Bella2017/p/10162506.html