15. 16. 923. | 雙指針題型

分析:
? 題目要求計算三個數(shù)之和為零,且這三元組不能重復(fù)。聯(lián)想到之前做過的“兩數(shù)之和”,我們可以先將數(shù)組排序,再將數(shù)組拆分成兩個部分來計算:
快慢指針:慢指針從起始遍歷到結(jié)束,記錄當前元素;快指針部分則對剩余元素進行“對撞指針”算法。
對撞指針:左指針和右指針分別從數(shù)組左右兩端遍歷,計算結(jié)果。

? 此題的一個難點是理清各種邊界問題,重復(fù)元素問題:
當數(shù)組長度小于3時,可以直接返回空結(jié)果。
在快慢指針循環(huán)中,若當前元素和前一個元素相同,則跳過該元素,不做計算;且若當前元素已經(jīng)大于0,直接返回已經(jīng)計算好的結(jié)果(因為后面的元素不可能再有三個相加為0的可能性)。
在對撞指針循環(huán)中,若右指針元素與前一個元素相同,則right--;若左指針元素與后一個元素相同,則left++;



分析:
? 和上一題相似的解題過程,我們只需要把對撞指針部分換成判斷距離是否更小就可以。

? 此外,這題其實可以考慮一下在雙指針的基礎(chǔ)上進一步優(yōu)化,比如去重、當距離為0可直接返回結(jié)果等。



分析:
? 還是老方法,直接將題目拆解成快慢指針和對撞指針兩個部分。題目要求三元組的全部排列組合結(jié)果,因此我們可以將解題步驟歸納成以下幾個步驟:
數(shù)組排序,進入快慢指針循環(huán);
當三元組和等于target時,計算相同元素的所有排列組合結(jié)果;
當三元組和大于target時,對撞指針的右指針往左移動;
當三元組和小于target時,對撞指針的左指針往右移動;
慢指針往右移動,直到遍歷結(jié)束。
? 該題的難點在于排列組合的計算,如[1,1,2,2,3,3],target = 6,我們需要分別遍歷計算2和3的個數(shù),然后利用排列組合計算公式算出他們跟1一共有幾種組合情況。
while(condition) left++,計算2的個數(shù)
while(condition) right--,計算3的個數(shù)
? 因此2和3一共有2*2種組合情況,然后再加上原來的結(jié)果即可。
? 注意,我們可能會遇到一種特殊情況,[1,1,2,2,2,2],即left和right的值是相同的。此時第一個while循環(huán)中,由于元素一直相同,因此最終left = right+1,導(dǎo)致left大于right,因此第二個while循環(huán)就不會進行。
? 因此這個時候的排列組合計算公式 (left - tl)*(tr - right) = 0,結(jié)果會是錯的。
? 但我們觀察發(fā)現(xiàn),其實這個時候只要把 right - left 就能直接得到重復(fù)元素2的個數(shù),就可以直接通過 排列組合計算公式得到答案。因此只需要多加一條判斷,來計算這種情況即可。
