力扣:三數之和---雙指針解法---C++實現

題目鏈接 

        https://leetcode-cn.com/problems/3sum/

題目描述

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

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

 

示例:

給定數組 nums = [-1, 0, 1, 2, -1, -4],

滿足要求的三元組集合爲:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

 

解題思路

  1. 最容易想到的思路就是暴力解法,寫個三重循環,把所有的情況都列舉一般,但是這種解法一般都會超時,而且題目中還說了不能有重複的三元組,就比如輸入的是-1,0,1,-1,0,1。這種在暴力的時候就會出現重複,所以還要想辦法去重,所以這種解法一般不可取。
  2. 題目中提到是是不重複,那我們是不是可以首先進行排序,然後在篩選的時候三個數a,b,c的時候,保證a<=b<=c。這樣是不是就少了一些重複的可能性,比如(a,b,c),(b,a,c),(c,b,a)這些就會被篩選掉了
  3. 當然滿足a<=b<=c並不能把所以重複的情況去掉。比如-1,-1,-1,0,0,0,0,1,1,1(排序後)。這樣根據上面的條件就無法解決了,下面說一個解決的辦法
  4. 比如我們在選其中a的時候,如果a選-1了,那接下來在遍歷的時候,a就不能在選-1.有沒有啥好辦法呢!辦法就是:我們在進行遍歷的時候,如果選a的這個數不是數組的第一個元素,那麼判斷一個這個數和這個數前面的數是否相等,如果相等,直接continue即可,因爲a已經選過了。
  5. 既然三重循環求解會超時,那麼我們可以先排序,再進行二重循環。
  6. 外層循環就是枚舉第一個數a,在這個外層循環的裏面首先要進行判斷a是否重複使用過了(使用上面4的方法),再定義一個變量,用來掃描數組c。
  7. 然後就開始第二層循環,這個循環是枚舉第二個數b,b從a後面的一個數開始枚舉(從左到右掃描),同時也要判斷b是否重複的問題,解決辦法和a一樣,在這二層循環裏面,再用一個while循環,從右到左掃描c
  8. 雖然是二層循環裏面套while循環,但是他並不是三重循環的時間複雜度。因爲假如我們在固定a的情況下,找到了一對b和c滿足了情況跟,接再來在枚舉b和c的時候,實在上一個找到的情況下進行繼續掃描的,如圖所示:

 

代碼

class Solution 
{
public:
    vector<vector<int>> threeSum(vector<int>& nums)
    {
        int len=nums.size();
        sort(nums.begin(),nums.end());
        vector<vector<int> > ans;
        //開始枚舉 a 
        for(int first=0;first<len;first++)
        {
        	//需要和上一次枚舉的數不相同 
            if(first>0&&nums[first]==nums[first-1])
                continue;
            int Target=-nums[first];
            // c 指向數組的最右端 
            int third=len-1;
            //開始枚舉b 
            for(int second=first+1;second<len;second++)
            {
            	//需要和上一次枚舉的數不相同 
                if(second>first+1&&nums[second]==nums[second-1])
                    continue;
                //需要保證b在c的左側 
                while(second<third&&nums[second]+nums[third]>Target)
                    third--;
                //如果指針重合,隨着b的增長,就不會有滿足a+b+c=0了 
                if(second==third)
                    break;
                if(nums[second]+nums[third]==Target)
                    ans.push_back({nums[first],nums[second],nums[third]});
            }
        }
        return ans;
    }
};

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章