leetcode:2sum,2sumSorted,3sum,3sumClosest,4sum,4sumII.[哈希表,双指针]

2sum:哈希表,再寻求a+b=c过程中可使用哈希表,一次遍历O(n)即可,使用unordered_map<int,int>之find()方法,思路:不存在于表->进哈希表;存在于表,得结果。注意如果不存在,返回[-1,-1],考虑问题要面面俱到。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {// O(n),C++ STL hash-->unoredered_map
        vector<int> ret(2,-1);
        unordered_map<int,int> hash;
        for (int i = 0; i < nums.size(); ++i)
        {
            if(hash.find(target-nums[i])==hash.end())
            {
                hash[nums[i]]=i;
            }else
            {
                ret[0]=i;
                ret[1]=hash[target-nums[i]]
            }
        }
        return ret;
        

    }
};

2sumSorted:已排序好的数组,直接使用双指针i,j前后逼近,时间复杂度O(logn)。

class Solution {// array is alreay sorted,we use double pointers
public:
    vector<int> twoSum_sorted(vector<int>& numbers, int target) {
        vector<int> ret(2,-1);
        int i=0,j=numbers.size()-1;
        while(i<j)
        {
            if(numbers[i]+numbers[j]==target)
            {
                ret[0]=i+1;
                ret[1]=j+1;
                return ret;
            }else if(numbers[i]+numbers[j]<target)
            {
                i++;
            }else
            {
                j--;
            }
        }
        return ret;
    }
};


3sum:先排序,然后,固定前面的k,后面双指针i,j逼近,注意有重复值时,可跳跃重复值。代码结构中,不能先跳跃重复值,再求和,因为,如果i一直跳跃,可能把j逼的动不了,[0,-2,1,1,3],i跳到1了,j无法跳到1.所以先求和,再跳跃!

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> res;
        sort(nums.begin(),nums.end());

        for (int k = 0; k <nums.size(); ++k)
        {
            if(nums[k]>0) break;
            if(k>0&&nums[k]==nums[k-1]) continue;

            int i=k+1,j=nums.size()-1;
            while(i<j)
            {
                //while(i<j&&nums[i]==nums[i+1]) i++;   we can not find this first,beacuse an example [0,-2,1,1,3]
                //while(i<j&&nums[j]==nums[j-1]) j--;
                if(nums[i]+nums[j]==0-nums[k])
                {
                    res.push_back({(nums[k],nums[i],nums[j])});
                    while(i<j&&nums[i]==nums[i+1]) i++;
                    while(i<j&&nums[j]==nums[j-1]) j--;
                    i++;
                    j--;
                }else if(nums[i]+nums[j]<0-nums[k])
                {
                    j--;
                }else
                {
                    i++;
                }
            }
        }
        return res;


    }
};


3sumClosest:三数之和sum比target小,为了更靠近target,sum就要增大!(无论正负,靠近就是增大或减小),不要想复杂了,跟二分逼近的原理一样的,擅长变通。

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        int mindis=1000000;
        int res;
        for (int k = 0; k < nums.size(); ++k)
        {
            if(k>0&&nums[k]==nums[k-1]) continue;

            int i=k+1,j=nums.size()-1;
            int sum;
            while(i<j)// a little translation of question 3sum,be flexible
            {         // first i++ then j-- is not right,beacuse it skips many combinations .it doesn't cover all
                sum=nums[k]+nums[i]+nums[j];
                if(sum==target) return sum;
                else if(sum<target)
                {
                    if(target-sum<mindis)
                    {
                        mindis=target-sum;
                        res=sum;
                    }
                    i++;
                }else
                {
                    if(sum-target<mindis)
                    {
                        mindis=sum-target;
                        res=sum;
                    }
                    j--
                }

            }
        }

        return res;

    }
};

4sum:3sum外面套一层循环即可

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> res;
        set<vector<int>> setvec;
        sort(nums.begin(),nums.end());
        for (int p = 0; p < nums.size(); ++p)
        {
            for (int k = p+1; k < nums.size(); ++k)
            {
                int i=k+1,j=nums.size()-1;
                while(i<j)
                {
                    int sum=nums[p]+nums[k]+nums[i]+nums[j];//3sum +for=4sum
                    if(sum==target)
                    {
                        setvec.insert({nums[p],nums[k],nums[i],nums[j]});
                        while(i<j&&nums[i]==nums[i+1]) i++;
                        while(i<j&&nums[j]==nums[j-1]) j--;
                        i++;
                        j--;
                    }else if (sum<target) i++;
                    else j--;
                }
            }
        }

        set<vector<int>>::iterator it= setvec.begin();
        for(;it!=setvec.end();++it)
        {
            res.push_back(*it);
        }
        return res;

    }
};


4sumII:unordered_map的迭代器用法,for(auto a:m1) a.first a.second. 能用哈希表的尽量用哈希表


class Solution {
public:
    int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
        int res=0;
        int len=A.size();
        unordered_map<int,int>m1,m2;
        for (int i = 0; i < len; ++i)
        {
            for (int j = 0; j < len; ++j)
            {
                m1[A[i]+B[j]]++;
                m2[C[i]+D[j]]++;
            }
        }
        for (auto a:m1)//knowing how to use iterator of unordered_map
        {
            res+=a.second*m2[0-a.first];
        }
        return res;
    }
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值