[leetcode] 3sum && 4sum
阿新 • • 發佈:2019-01-13
- 題意:給定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);
}