LeetCode 15.3つの数字の合計【JavaScript】

三数之和

n個の整数を含む配列numsが与えられた場合、a + b + c = 0となるように、numsに3つの要素a、b、cがあるかどうかを判別します。条件を満たす、繰り返されないすべてのトリプルを見つけてください。

注:回答に繰り返しトリプルを含めることはできません。

例:

配列nums = [-1、0、1、2、-1、-4]が与えられた場合、

要件を満たすトリプルのセットは次のとおりです:
[
[-1、0、1]、
[-1、-1、2]
]

出典:LeetCode
リンク:https ://leetcode-cn.com/problems/3sum
著作権はLeetCodeが所有しています商用の再版については、公式の承認に連絡してください。非商用の再版については、出典を示してください。

私はこの質問に1日立ち往生し、重いカードに長い時間を費やし、制限時間を超えてさらに半日立ち往生しました。それで、それを記録する必要があると思いました。
このつらい記録を見ると、行の間に2つの単語があります:a〜tui!リトルチキン!
録音
私の最初のアイデアは、配列を小さいものから大きいものに並べ替え、nums [i]を変更せずに修正し、nums [i +1]をnums [l]、最後の桁nums [nums.length-1]に割り当てることでした。 nums [r]に値を割り当て、nums [i]、nums [l]、nums [r]の3つの数値の合計を計算して、0かどうかを判断し、それが満たされたときに結果セットに追加します。合計<0の場合、l ++; sumsum> 0の場合、r-
当時の私のコードは次のようでした

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
   var t=[];
    nums.sort((a, b) => a - b);
 for(let i=0;i<nums.length;i++){
     let l=i+1;
     r=nums.length-1;
     while(l<r){
     if(nums[i]+nums[l]+nums[r]==0){
       t.push([nums[i],nums[l],nums[r]]);
       l++; r--;
            }
     else if(nums[i]+nums[l]+nums[r]<0){l++;}
     else{r--;}
     }
 }
   return t;
};

次に、重複排除を考慮していなかったことがわかり、出力結果は次のようになりました。
エラー例1
そこで、Setを使用して重複排除を行うことを考えました。現時点では、コードは次のようになっています。

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    var t=[];
    nums.sort((a, b) => a - b);
 for(let i=0;i<nums.length;i++){
     let l=i+1;
     r=nums.length-1;
     while (nums[i] === nums[++i]) {} 
     while(l<r){
     if(nums[i]+nums[l]+nums[r]==0){
       t.push([nums[i],nums[l],nums[r]]);
       l++; r--;
     }
     else if(nums[i]+nums[l]+nums[r]<0){l++;}
     else{r--;}
     }
 }
   var newArr = new Set(t);
   var arr1 = [...newArr];
   return arr1;
};

その後、結果が変わらないことに戸惑い、バイドゥを検索して大物に質問したところ、設定方法はオブジェクトの値ではなく、メモリアドレスを判断することであることがわかりました。まあ、それは本当に私の新人です。
次に、他の人のロジックを参照した後、コードを次のように変更しました。

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums) {
    var t=[];
    nums.sort((a, b) => a - b);
 for(let i=0;i<nums.length;i++){
     if (nums[i] > 0) break;
    if (i > 0 && nums[i] === nums[i - 1]) continue;//去重
     let l=i+1;
     r=nums.length-1;
     while(l<r){
     if(nums[i]+nums[l]+nums[r]==0){
       t.push([nums[i],nums[l],nums[r]]);
       while (l < r && nums[l] === nums[l + 1]) l++;//去重
        while (l < r && nums[r] === nums[r - 1]) r--;//去重
         l++; r--;
     }
     else if(nums[i]+nums[l]+nums[r]<0){l++;}
     else{r--;}
     }
 }
   return t;
};

合格しました!さらに、ビッグガイのソリューションが含まれています。今回は、ビッグガイの広告を掲載します(パブリックアカウント:ビッグフロントエンドについて話します。毎週のコンテストのソリューションには強力な控除があり、すべてフロントエンドの人々にとってよりフレンドリーなJavaScriptを使用しています):

/**
 * @param {number[]} nums
 * @return {number[][]}
 */
var threeSum = function(nums){
    var t=[];
    var i=0;
    var len=nums.length;
    nums.sort((a, b) => a - b);
    const record = new Set();
    while(i<len)
{
    if(nums[i]>0) break;
     let l=i+1;
     r=len-1;
     while(l<r){
         var sum=nums[i]+nums[l]+nums[r];
     if(sum==0){
       const key=[nums[i],nums[l],nums[r]].sort().join(',');
       if (!record.has(key)) {
           t.push([nums[i],nums[l],nums[r]]);
         record.add(key);}
         l++; r--;
     }
     else if(sum<0){l++;}
     else{r--;}
     i++;
     }
}
 return t;
};

しかし、これは制限時間を超えています。誰かがこれを最適化する方法があるかどうかはわかりません。指摘してください。

おすすめ

転載: blog.csdn.net/weixin_42345596/article/details/106027146