1. 程式人生 > >[leetcode] 3sum && 4sum

[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); }