1. 程式人生 > >【LeetCode & 劍指offer刷題】陣列題3:3Sum(系列) + 4sum

【LeetCode & 劍指offer刷題】陣列題3:3Sum(系列) + 4sum

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...)

3Sum

Given an array   nums   of   n   integers, are there elements   a ,   b ,   c   in   nums
  such that   a   +   b   +   c   = 0? Find all unique triplets in the array which gives the sum of zero. Note: The solution set must not contain duplicate triplets.
Example: Given array nums = [-1, 0, 1, 2, -1, -4],   A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
C++
  //問題:找陣列中和為0的三元組 //方法:排序後,掃描陣列,轉化為2sum問題 //2sum對應一個迴圈,3sum對應兩重迴圈,4sum對應三重迴圈 //O(n^2) #include <algorithm> class Solution { public :     vector < vector < int >> threeSum ( vector < int >& a )     {         vector < vector < int >> res ;         int n = a . size ();         if ( n < 3 ) return res ;                 sort (a.begin(), a.end()); //排序           //掃描a[i],後面在用leftright首尾兩指標掃描         for ( int i = 0 ; i < n && a [ i ]<= 0 ; i ++) //第一個數只能是負數或0,加此判斷以節省時間,如果不加次判斷,則i<n-2即可         {             int target = - a [ i ]; //將第一個數的相反數定為2sum的target              int left = i+1//i=0~n-3             int right = n-1;               while ( left < right ) //用兩個指標分別從a[i+1]和整個陣列末尾開始向中間掃描 ,找到所有可以滿足和為-a[i]的數對             {                 int sum = a [ left ] + a [ right ];                 if ( sum < target ) left ++; //僅移動前面指標                 else if ( sum > target ) right --; //僅移動後面指標                 else //滿足3sum要求                 {                     res . push_back ( { a [ i ], a [ left ], a [ right ]});   //將滿足的三元組push到結果向量中(也可以用vector<int>{a[i], a[left], a[right]})                       while ( left < right && a [ left + 1 ] == a [ left ]) left ++; //以免第二個數重複                     while ( left < right && a [ right - 1 ] == a [ right ]) right --; //以免第三個數重複                     left ++; // 前後指標都移動,下一次判斷                     right --;                 }             }             while ( i + 1 < n && a [ i + 1 ] == a [ i ]) i ++; //以免第一個數重複         }                 return res ;     } }; /*注: 也可用set避免重複 set<vector<int>> res; ... vector<vector< int >> (res.begin(), res.end());//用迭代器將set轉為vector */   16 .   3Sum Closest Given an array   nums   of   n   integers and an integer   target , find three integers in   nums  such that the sum is closest to  target . Return the sum of the three integers. You may assume that each input would have exactly one solution. Example: Given array nums = [-1, 2, 1, -4], and target = 1.   The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
  /* 問題:離目標值最近的三數之和 方法:排序後,掃描 a[i], 後面在用 left right 首尾兩指標掃描 */ class Solution { public :     int threeSumClosest ( vector < int >& nums , int target )     {         if ( nums . size ()< 3 ) return 0 ;                 int closest = nums [ 0 ] + nums [ 1 ] + nums [ 2 ];         int diff = abs ( closest - target );         sort (nums.begin(), nums.end()); //排序                 //掃描a[i],後面在用leftright首尾兩指標掃描         for ( int i = 0 ; i < nums . size () - 2 ; i ++)   //i=0~n-3(n-2,n-1 分別為 left right 佔著 )         {             int left = i + 1 , right = nums . size () - 1 ; // left = i+1, right=n-1                         while ( left < right )             {                 int sum = nums [ i ] + nums [ left ] + nums [ right ];                 int newDiff = abs ( sum - target );                 if ( newDiff <  diff ) // 更新 diff sum                 {                     diff = newDiff ;                     closest = sum ;                 }                                 if ( sum < target ) left ++; // 調節指標                 else right --;             }         }         return closest ;     } };   18. 4Sum 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] ]
Seen this question in a real interview before?   Yes No     /* 問題:找與目標值相等的 4 個數 三重迴圈即可 set 可避免重複結果 */ class Solution { public :     vector < vector < int >> fourSum ( vector < int > & nums , int target )     {         if ( nums . size () < 4 ) return vector < vector < int >>(); // 或者用 {{}}                 set <vector<int>> res;         sort ( nums . begin (), nums . end ());                 // 掃描 a[i],a[j] 後面接 left,right 兩個指標         for ( int i = 0 ; i < int ( nums . size () - 3 ); i ++)         {             for ( int j = i + 1 ; j < int ( nums . size () - 2 ); j ++)             {     //            if (j > i + 1 && nums[j] == nums[j - 1]) continue; // 遇到重複數時不執行下面語句,如果用 set 可以不進行此判斷                                 int left = j + 1, right = nums.size() - 1//i=0~n-4,j=i+1~n-3                 while ( left < right )                 {                     int sum = nums [ i ] + nums [ j ] + nums [ left ] + nums [ right ];                     if ( sum == target )                     {                         vector < int > out { nums [ i ], nums [ j ], nums [ left ], nums [ right ]};                         res . insert ( out ); // set, 當有重複結果時,插入會失敗                         left ++; right --;                     }                     else if ( sum < target ) left ++;                     else right --;                 }             }         }         return vector < vector < int >>( res . begin (), res . end ()); //set轉化為vector輸出     } };