Given an array nums
of n integers and an integer target
, are there elements a, b, c, and d in nums
such that a + b + c + d = target
? Find all unique quadruplets in the array which gives the sum of target
.
Note:
The solution set must not contain duplicate quadruplets.
Example:
Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.
A solution set is:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
A solution set is:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]
求四个数的和的话可以降为求三个数的和
class Solution { public: vector<vector<int>> fourSum(vector<int>& nums, int target) { vector<vector<int>> res; if(nums.size()<4) return res; sort(nums.begin(),nums.end()); for(int i=0;i<nums.size()-1;i++){ cout<<"----------------"<<endl; if(4*nums[i]>target) //值已经超了 break; //int tar3=target-nums[i]; int tar3=target-nums[i]; //cout<<target<<" "<<i<<endl; threeSum(nums,res,tar3,i); } return res; } void threeSum(vector<int>& nums,vector<vector<int>>&result,int tar3,int start){//start表示的是计算四个数的和的第一个数 if(start>0){ while(nums[start]==nums[start-1]) //如果这个和前面的相同的话,这个就直接结束好了,再继续下去反而会接着出现问题 return; } for(int i=start+1;i<nums.size()-1;i++){ cout<<i<<endl; int target=tar3-nums[i]; int front=i+1; int back=nums.size()-1; while(front<back){ if(nums[front]+nums[back]==target){ vector<int> temp; temp.push_back(nums[start]); temp.push_back(nums[i]); temp.push_back(nums[front]); temp.push_back(nums[back]); result.push_back(temp); while(front<back&&nums[front]==temp[2]) front++; while(front<back&&nums[back]==temp[3]) back--; //哇塞哇塞在这里出现了死循环 //while(front<back&&nums[front]==temp[1]) front++; //while(front<back&&nums[back]==temp[2]) back--; } else if(nums[front]+nums[back]<target) front++; else if(nums[front]+nums[back]>target) back--; } while((nums[i]==nums[i+1])&&((i+1)<nums.size())){ i++; } } } };
求三个数的和仍然使用两个指针,但是由于加了一道步骤所以参数多了,再加上自己命名变量的时候名字有时候会发生重复,所以就导致有点懵。
参数命名的时候需要更加清晰一点啦
而且这次似乎有点得意忘形,所以写的马虎点,于是调了很久。
另外,bug还是要用纸笔一行一行的调。
这个代码是在讨论区看到的,他的优势是把各种情况都考虑的很全面,程序运行起来的话如果遇到这种情况就可以直接结束这次循环,而不是嵌套进去再一点一点的验证,但是这种频繁的判断语句是否也会浪费时间呢,两者相比起来哪个更快一点呢
呀,这个时候明白了计组和操作系统在代码编写中的作用,尤其是c,c++这样与底层相关的语言。
有一个问题,在使用容器的size时是每次都调用函数快还是在一开始就定义一个变量好呢,想必是第二种方式吧。
class Solution { public List<List<Integer>> fourSum(int[] nums, int target) { ArrayList<List<Integer>> res = new ArrayList<List<Integer>>(); int len = nums.length; if (nums == null || len < 4) return res; Arrays.sort(nums); int max = nums[len - 1]; if (4 * nums[0] > target || 4 * max < target) return res; int i, z; for (i = 0; i < len; i++) { z = nums[i]; if (i > 0 && z == nums[i - 1])// avoid duplicate continue; if (z + 3 * max < target) // z is too small continue; if (4 * z > target) // z is too large break; if (4 * z == target) { // z is the boundary if (i + 3 < len && nums[i + 3] == z) res.add(Arrays.asList(z, z, z, z)); break; } threeSumForFourSum(nums, target - z, i + 1, len - 1, res, z); } return res; } /* * Find all possible distinguished three numbers adding up to the target * in sorted array nums[] between indices low and high. If there are, * add all of them into the ArrayList fourSumList, using * fourSumList.add(Arrays.asList(z1, the three numbers)) */ public void threeSumForFourSum(int[] nums, int target, int low, int high, ArrayList<List<Integer>> fourSumList, int z1) { if (low + 1 >= high) return; int max = nums[high]; if (3 * nums[low] > target || 3 * max < target) return; int i, z; for (i = low; i < high - 1; i++) { z = nums[i]; if (i > low && z == nums[i - 1]) // avoid duplicate continue; if (z + 2 * max < target) // z is too small continue; if (3 * z > target) // z is too large break; if (3 * z == target) { // z is the boundary if (i + 1 < high && nums[i + 2] == z) fourSumList.add(Arrays.asList(z1, z, z, z)); break; } twoSumForFourSum(nums, target - z, i + 1, high, fourSumList, z1, z); } } /* * Find all possible distinguished two numbers adding up to the target * in sorted array nums[] between indices low and high. If there are, * add all of them into the ArrayList fourSumList, using * fourSumList.add(Arrays.asList(z1, z2, the two numbers)) */ public void twoSumForFourSum(int[] nums, int target, int low, int high, ArrayList<List<Integer>> fourSumList, int z1, int z2) { if (low >= high) return; if (2 * nums[low] > target || 2 * nums[high] < target) return; int i = low, j = high, sum, x; while (i < j) { sum = nums[i] + nums[j]; if (sum == target) { fourSumList.add(Arrays.asList(z1, z2, nums[i], nums[j])); x = nums[i]; while (++i < j && x == nums[i]) // avoid duplicate ; x = nums[j]; while (i < --j && x == nums[j]) // avoid duplicate ; } if (sum < target) i++; if (sum > target) j--; } return; } }