【Leetcode】18. 四数之和(加一点小总结)

Leetcode

1.问题描述

在这里插入图片描述

2.解决方案


解法一:排序加双指针

a.思路

在这里插入图片描述

b.分析总结

1.int 32位,能表示2147483647 ,大概是2*10^9 , 就是说如果题目的数有10^9,那就要注意了两个以上加起来就超过了 int 能表示范围,比如这道题,所以要记住 int 范围的事情。
int 四字节能表示在这里插入图片描述
在这里插入图片描述
解决这个问题就是把每一个nums元素强转为long long,或者也可以重建一个新的vector< long long> nums,重新赋值但是感觉有点慢,不如直接强转。并且target还是 int 不用转化

if ((long long )nums.at(first)+(long long )nums.at(second)+(long long )nums.at(left)+(long long )nums.at(right)==target)

2.这个检查重复点的处理

//重复性
//if(second!=1&&nums.at(second)==nums.at(second-1)) continue;
if(second!=first+1&&nums.at(second)==nums.at(second-1)) continue;
c.代码实现
//排序加双指针
class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ans;
        int len=nums.size();
        //可行性
        if(len<4) return ans;
        sort(nums.begin(),nums.end());

        for(int first=0;first<len;first++){
            //重复性
            if(first!=0&&nums.at(first)==nums.at(first-1)) continue;
            for(int second=first+1;second<len;second++){
                //重复性
                //if(second!=1&&nums.at(second)==nums.at(second-1)) continue;
                if(second!=first+1&&nums.at(second)==nums.at(second-1)) continue;
                int left=second+1;
                int right=len-1;

                while (left<right){
                    if ((long long )nums.at(first)+(long long )nums.at(second)+(long long )nums.at(left)+(long long )nums.at(right)==target){
                        vector<int> t;
                        t.push_back(nums.at(first));
                        t.push_back(nums.at(second));
                        t.push_back(nums.at(left));
                        t.push_back(nums.at(right));
                        ans.push_back(t);

                        while ((left+1)<len&&nums.at(left)==nums.at(left+1)) left++;
                        left++;
                        while ((right-1)>0&&nums.at(right)==nums.at(right-1)) right--;
                        right--;

                        continue;
                    }
                    if ((long long )nums.at(first)+(long long )nums.at(second)+(long long )nums.at(left)+(long long )nums.at(right)>target){
                        while ((right-1)>0&&nums.at(right)==nums.at(right-1)) right--;
                        right--;

                        continue;
                    }
                    if((long long )nums.at(first)+(long long )nums.at(second)+(long long )nums.at(left)+(long long )nums.at(right)<target){
                        while ((left+1)<len&&nums.at(left)==nums.at(left+1)) left++;
                        left++;

                        continue;
                    }


                }

            }
        }

        return ans;
    }
};

解法二:排序加双指针(官方优化)

没考虑int越界问题,并且在简化判断中,会出现nums访问越界问题,先不管了,重要的是思路!

优化点一:在两个for开始之际,也就是在遍历一个序列之际,总会有些特殊情况显然不符合条件,那么我们需要找出来并且提前剔除,节省时间(这个适用于所有for开始之际,以后每个for都要往这方面考虑)!
//新加入简化判断
if (nums.at(first) + nums.at(first+1) + nums.at(first+2) + nums.at(first+3) > target) break;
if (nums.at(first) + nums.at(len - 3) + nums.at(len - 2) + nums.at(len - 1) < target) continue;


//新加入简化判断
if (nums.at(first) + nums.at(second) + nums.at(second+1) + + nums.at(second+2) > target) break;
if (nums.at(first) + nums.at(second) + nums.at(len - 2) + nums.at(len - 1) < target) continue;
优化点二:反复进行计算的提前计算,也好统一管理
//新加入提前计算
int sum = nums.at(first)+nums.at(second)+nums.at(left)+nums.at(right);
if (sum==target)
//排序加双指针(官方优化)
class Solution1 {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>> ans;
        int len=nums.size();
        //可行性
        if(len<4) return ans;
        sort(nums.begin(),nums.end());

        for(int first=0;first<len;first++){
            //重复性
            if(first!=0&&nums.at(first)==nums.at(first-1)) continue;

            //新加入简化判断
            if (nums.at(first) + nums.at(first+1) + nums.at(first+2) + nums.at(first+3) > target) break;
            if (nums.at(first) + nums.at(len - 3) + nums.at(len - 2) + nums.at(len - 1) < target) continue;


            for(int second=first+1;second<len;second++){
                //重复性
                //if(second!=1&&nums.at(second)==nums.at(second-1)) continue;
                if(second!=first+1&&nums.at(second)==nums.at(second-1)) continue;


                //新加入简化判断
                if (nums.at(first) + nums.at(second) + nums.at(second+1) + + nums.at(second+2) > target) break;
                if (nums.at(first) + nums.at(second) + nums.at(len - 2) + nums.at(len - 1) < target) continue;


                int left=second+1;
                int right=len-1;

                while (left<right){

                    //新加入提前计算
                    int sum = nums.at(first)+nums.at(second)+nums.at(left)+nums.at(right);

                    if (sum==target){
                        vector<int> t;
                        t.push_back(nums.at(first));
                        t.push_back(nums.at(second));
                        t.push_back(nums.at(left));
                        t.push_back(nums.at(right));
                        ans.push_back(t);

                        while ((left+1)<len&&nums.at(left)==nums.at(left+1)) left++;
                        left++;
                        while ((right-1)>0&&nums.at(right)==nums.at(right-1)) right--;
                        right--;

                        continue;
                    }
                    if (sum>target){
                        while ((right-1)>0&&nums.at(right)==nums.at(right-1)) right--;
                        right--;

                        continue;
                    }
                    if(sum<target){
                        while ((left+1)<len&&nums.at(left)==nums.at(left+1)) left++;
                        left++;

                        continue;
                    }


                }

            }
        }

        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值