1. 程式人生 > >領釦刷題---15.三數之和

領釦刷題---15.三數之和

題目要求:

給定一個包含 n 個整數的陣列 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。

注意:答案中不可以包含重複的三元組。

小白第一次寫部落格,希望大佬多多指教。

這是一道在領釦上標記為中等的陣列題目,題目的難點在於去除重複的三元組。我們想去除重複的元素,就要先弄清楚,重複的答案是如何出來的,按照正常的思路,我們可以跑一個三層for迴圈,每一次都不斷由前面的和後面的匹配,直到所有的組合被匹配完畢,滿足要求的答案被找到,但是在跑的過程中如果前面的數有和後面的數重複的,那我們跑的過程中必然會將其記錄兩次。弄清楚了重複的原因,現在就需要想辦法去除重複。這樣問題就變成了陣列的去重,陣列去重我們一般採用的都是先排序的方式,前面與後面對比,去重。

按照我們的思路程式碼如下:

//程式語言c++

class Solution { public:     vector<vector<int>> threeSum(vector<int>& nums) {         vector<vector<int>> a;//建立容器       int len=nums.size();         vector<int>temp;//中間變數,用於後面儲存每一次找到的結果         if(nums.size()<=2)             return a;//如果所給的陣列長度小於3,直接返回         sort(nums.begin(),nums.end());//使用sort方法對資料進行排序         int i,j,k,sum;         for(i=0;i<len-2;i++)//第一層迴圈         {             if(nums[i]>0)//nums[0]如果大於0代表資料都為正數,直接退出                 break;             if(i>0&&nums[i]==nums[i-1])//用於去除重複值,只使用第一次出現的資料                 continue;             j=i+1;             while(j<=len-2)             {                                  if(j>i+1&&nums[j]==nums[j-1])//去重                     {                        j++;                        continue;                                               }                 k=j+1;                 while(k<=len-1)                 {                      if(k>j+1&&nums[k]==nums[k-1])//去重                     {                        k++;                        continue;                                               }                 sum=nums[i]+nums[j]+nums[k];                 if(sum==0)                 {                                          temp.push_back(nums[i]);                     temp.push_back(nums[j]);                     temp.push_back(nums[k]);                     a.push_back(temp);                     temp.clear();//清空                     k++;                                         }                 else                     k++;               }                  j++;             }                      }

    return a; } };

提交之後,會提示超時,所以我們改進程式碼,考慮到存在的三重for迴圈是為了得到和0匹配的結果,在借鑑了大佬的方法之後,我們可以將其改為二重迴圈,利用前後向中間靠的原則,尋找答案。這是一種程式設計的基本技巧,如果沒有掌握可以借鑑學習,改變後的程式碼如下:

class Solution { public:     vector<vector<int>> threeSum(vector<int>& nums) {         vector<vector<int>> a;       int len=nums.size();         vector<int>temp;         if(nums.size()<=2)             return a;         sort(nums.begin(),nums.end());         int i,j,k,sum;         for(i=0;i<len-2;i++)         {             if(nums[i]>0)                 break;             if(i>0&&nums[i]==nums[i-1])                 continue;             j=i+1;//未匹配資料的前端             k=len-1;未匹配資料的後端             while(j<k)//如果出現交叉,則代表後面的資料都匹配完畢             {                                  if(j>i+1&&nums[j]==nums[j-1])//用於去除重複值,由於k每次都是找到就跳出,所以不用去重操作                     {                        j++;                        continue;                                               }                 sum=nums[i]+nums[j]+nums[k];                 if(sum==0)//儲存資料                 {                                          temp.push_back(nums[i]);                     temp.push_back(nums[j]);                     temp.push_back(nums[k]);                     a.push_back(temp);                     temp.clear();                     j++;                                         }                 else if(sum>0)//如果大於0代表資料過大則將k減小,則匹配的k值減小                     k--;                 else                 j++;                              }                      }

    return a; } };

可以發現這一次很輕鬆就通過了,完成了這道題目之後我們可以嘗試去做16,18兩題,思路大致相同。