LeetCode刷题——题目15、16、17、18

15:三数之和

 解题:排序+双指针(b和c就代表双指针)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        if(nums.size()<3) return result;
        sort(nums.begin(),nums.end());   //排序
        if(nums[0]>0) return result;
        int sum;
        int a=0;
        while(a<nums.size()){
            if(nums[a] >0) return result;
            int b=a+1,c=nums.size()-1;   //b从a的右边第一个开始,c从最后一个开始
            while(b<c){
                sum=nums[a]+nums[b]+nums[c];
                if(sum>0) {  //sum大了说明c要往左移动
                    c--;
                }
                else if(sum<0){  //sum小了说明b王右边移动
                    b++;
                }
                else{
                    result.push_back({nums[a],nums[b],nums[c]});
                    while(c>b && nums[c]==nums[c-1]){c--;}  //跳过相同的
                    while(c>b && nums[b]==nums[b+1]){b++;}  //跳过相同的
                    c--;
                    b++;
                }
            }
            while(a+1<nums.size() &&nums[a] == nums[a+1]){a++;}  //避免第一个数就开始重复,比如-1 -1 0 1 2 4这个例子,没有这个会出错
            a++;
        }
        return result;
    }
};

通过结果:

 16.最接近的三数之和

解题:啃上一题的老本……比上一个简单

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        if(nums.size()==3) return nums[0]+nums[1]+nums[2];
        int a=0;
        int res=nums[0]+nums[1]+nums[2];
        while(a<nums.size()-2){
            int b=a+1,c=nums.size()-1;
            while(b<c){
                int sum=nums[a]+nums[b]+nums[c];
                if(sum>target) {  //sum大了说明c要往左移动
                    res=abs(target-sum)>abs(target-res)?res:sum;
                    c--;
                }
                else if(sum<target){  //sum小了说明b往右边移动
                    res=abs(target-sum)>abs(target-res)?res:sum;
                    b++;
                }
                else{
                    return target;
                }
            }
            a++;
        }
        return res;
    }
};

通过结果:

17.电话号码的字母组合

解题:我是笨蛋

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        //分解问题:1.识别数字对应的字母->2.高效的排列组合
        vector<string> s,s1;
        int len=digits.size();
        if(len==0) return s1;
        //把数字转化成字符串
        for(int i=0;i<len;i++){
            switch(digits[i]){
            case '2':
                s.push_back("abc");
                break;
            case '3':
                s.push_back("def");
                break;
            case '4':
                s.push_back("ghi");
                break;
            case '5':
                s.push_back("jkl");
                break;
            case '6':
                s.push_back("mno");
                break;
            case '7':
                s.push_back("pqrs");
                break;
            case '8':
                s.push_back("tuv");
                break;
            case '9':
                s.push_back("wxyz");
                break;
            default:
                break;
            }
        }
        string temp="";
        if(len == 1){
            int len1=s[0].size();
            for(int i=0;i<len1;i++){
                temp=s[0][i];
                s1.push_back(temp);
            }
        }
        if(len == 2){
            int len1=s[0].size();
            int len2=s[1].size();
            for(int k=0;k<len1;k++){
                for(int m=0;m<len2;m++){
                    temp=s[0][k];
                    temp.push_back(s[1][m]);
                    s1.push_back(temp);
                }
            }
        }
        if(len==3){
            int len1=s[0].size();
            int len2=s[1].size();
            int len3=s[2].size();
            for(int k=0;k<len1;k++){
                for(int m=0;m<len2;m++){
                    for(int p=0;p<len3;p++){
                        temp=s[0][k];
                        temp.push_back(s[1][m]);
                        temp.push_back(s[2][p]);
                        s1.push_back(temp);
                    }
                }
            }
        }
        if(len==4){
            int len1=s[0].size();
            int len2=s[1].size();
            int len3=s[2].size();
            int len4=s[3].size();
            for(int k=0;k<len1;k++){
                for(int m=0;m<len2;m++){
                    for(int p=0;p<len3;p++){
                        for(int q=0;q<len4;q++){
                            temp=s[0][k];
                            temp.push_back(s[1][m]);
                            temp.push_back(s[2][p]);
                            temp.push_back(s[3][q]);
                            s1.push_back(temp);
                        }
                    }
                }
            }
        }
        return s1;
    }
};

通过结果:

 优化:一种思路就是回溯。也有用到了图的深度遍历DFS。还有动态规划、不回溯求余的(这个思路比较特别,有空写,顺便详细写一篇数据结构的BFS和DFS)

18:四数之和

 解题:

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int> > ret;  //大容器
        int len=nums.size();
        if(len<4) return ret;
        sort(nums.begin(),nums.end());
        //两个循环+双指针=四个数
        for(int i=0;i<len-3;i++){
            if(i>0 && nums[i] == nums[i-1]) continue;
            for(int j=i+1;j<len-2;j++){
                if(j>i+1 && nums[j] == nums[j-1]) continue;
                long long sum=(long long)nums[i]+(long long)nums[j];
                int left=j+1;
                int right=len-1;
                while(left<right){
                    int s=sum+nums[left]+nums[right];
                    if(s < target) left++;
                    else if(s > target) right--;
                    else {
                        ret.push_back(vector<int>{nums[i],nums[j],nums[left],nums[right]});
                        while(left<right && nums[left] == nums[++left]);
                        while(left<right && nums[right] == nums[--right]); 
                    }
                }
            } 
        }
        return ret;
    }
};

通过结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值