[leetcode] 3sum && 4sum

  • 题意:给定n个数,让我们在其中选择3个或者是4个,使其的和等于一个target,找出所有的存在的解法,并没有重复。
  • 本质上是对2sum的扩展,我们在面对2Sum问题的时候,首先对数组nums进行一个排序,然后维护两个指针,一个从小到大,一个从大到小的遍历整个数组,直到这两个指针相遇。
- r=0, l=nums.size()
- 当r<l的时候
	- 如果nums[r] + nums[l] < target: r+=1
	- 如果nums[r] + nums[l] > target: l -= 1
	- 如果两个相等,则我们找到一组解{nums[l], nums[r]},然后我们再依次遍历,直到找到不同的l和r,避免出现重复的解。
  • 2Sum问题的解法如上所示,那么对于我们的N Sum问题,我们可以使用递归的方法来逐渐将N Sum问题转化为2Sum问题。
1、定义nums, N, target, new_list{维护现有的list}
2、如果N小于2,则转入2SUM算法求解,不同的在于如果找到解的话,解需要merge new_list
3、如果N大于2,则遍历nums
	- 对于nums 中的第i个元素,我们
	- new_list.append(nums[i]),
	- target -= nums[i],
	- nums = nums[i:]
	- N -= 1
	- 将更新后的这些参数传递到第2步骤,进行递归。
	- 注意⚠️,为了避免重复,如果nums[i] == nums[i-1],我们则跳过当前的i。
	- 注意,这里不能是nums[i] == nums[i+1],则跳过i,因为删除nums里面原有元素的重复性。
	- 恢复parameter,继续循环
  • 具体实现的Code:
vector<vector<int>> find_result(vector<int> nums, int target, vector<vector<int>>& res, vector<int> newLists, int n){
        // 代表从nums里面挑出来n个数的和等于target
        if(n < 2){
            return res;
        }
        if(n == 2){
            int front = 0;
            int end = nums.size()-1;

            while(front < end){
                if((nums[front] + nums[end]) < target){
                    front += 1;
                }else{
                    if((nums[front] + nums[end]) > target){
                        end -= 1;
                    }else{
                        vector<int> solution = {nums[front], nums[end]};
                        solution.insert(solution.end(),newLists.begin(), newLists.end());
                        while(front < end && nums[front] == nums[front + 1]){
                            front += 1;
                        }
                        while(front < end && nums[end] == nums[end - 1]){
                            end -= 1;
                        }
                        res.push_back(solution);
                        front += 1;
                        end -= 1;
                    }
                }
            }
        }else{
            for(int i=0;i<nums.size();i++){
                if(i == 0 || nums[i] != nums[i-1]){
                //if(i == nums.size() - 1 || nums[i] != nums[i+1]){
                    newLists.push_back(nums[i]);
                    // vector<int> new_nums = vector<int>(nums.begin() + i + 1, nums.end());
                    find_result(vector<int>(nums.begin() + i + 1, nums.end()), target - nums[i], res, newLists, n-1);
                    newLists.pop_back();
                }
            }
        }
        return res;
    }
vector<vector<int>> fourSum(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> res = vector<vector<int>>();
//        for(int i=0;i<nums.size();i++){
//            for(int j=i+1;j<nums.size();j++){
//                int front = j + 1;
//                int end = nums.size() - 1;
//                while(front < end){
//                    if((nums[i] + nums[j] + nums[front] + nums[end]) < target){
//                        front += 1;
//                    } else{
//                        if((nums[i] + nums[j] + nums[front] + nums[end]) > target){
//                            end -= 1;
//                        }else{
//                            vector<int> solution = {nums[i], nums[j], nums[front], nums[end]};
//                            res.push_back(solution);
//                            while(front < end && nums[front] == nums[front + 1]){
//                                front += 1;
//                            }
//                            while(front < end && nums[end] == nums[end - 1]){
//                                end -= 1;
//                            }
//                            front += 1;
//                            end -= 1;
//                        }
//                    }
//                }
//                while(j < nums.size() - 1 && nums[j] == nums[j+1]){
//                    j++;
//                }
//            }
//            while(i < nums.size() - 1 && nums[i] == nums[i+1]){
//                i++;
//            }
//        }
//        return res;
        return find_result(nums, target, res, vector<int>(), 4);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值