blog

リーコード|常連ダブルポインターアルゴリズム問題

leetcode|クラシカルパワーバックル第1問 この3つの数の和の問題をシェアします。ちょっと難しいかもしれませんので、賢い頭を使って、一緒に粘っていただければと思います! 今日の笑い 私より優秀な...

Feb 24, 2020 · 3 min. read
Share this

今日はケビンのアルゴリズムの旅の21日目です。リートコード問題15を説明するつもりですが、昨日の説明を使って

今回は、3つの数字の和のパズルです。ちょっと難しいかもしれませんので、賢い頭脳を使って、くっついてみてくださいね。

デイリースマイル

私より優れた人たちが努力しないのなら、その人たちは私より優れているのでしょうか?

問題 説明

n 個の整数を含む配列 nums が与えられたとき、a + b + c = 0 となるような 3 つの要素 a, b, c が nums に存在するかどうかを判定しなさい。条件を満たし、重複しない3つの要素をすべて求めなさい。

注:回答には重複したトリプルを含めないでください。

nums = [-1, 0, 1, 2, -1, -4] という配列が与えられます。

要件を満たすトリプルの集合は次のとおりです: [ [-1, 0, 1], [-1, -1, 2] ]。

問題解決

ダブルポインター

この問題のアルゴリズムの考え方は以下の通り:

  1. 特殊な判定として、配列の長さがnの場合、配列がnullか配列の長さが3未満の場合は[]をそのまま返します。
  2. 配列をソートします。
  3. ソートされた配列を繰り返します:
    • nums[i]>0の場合:すでにソートされているので、その後に0を足す数字が3つ続くことはありません。
    • 要素が重複している場合:重複解を避けるためにスキップします。
    • 左ポインタL = i + 1、右ポインタR = n - 1となるようにします。
      • nums[i]+nums[L]+nums[R]==0のとき、結果集合に要素を追加する要件を満たし、ループを実行し、次の位置で左境界と右境界が重複しているかどうかを判断し、重複解を削除します。同時にL,Rを次の位置に移動して新しい解を求めます。
      • 和が0より大きい場合は、nums[R]が大きすぎるので、Rを左に移動します。
      • 和が 0 より小さい場合は、nums[L] が小さすぎるので、L を右に移動します。

コードの実装

//go
func threeSum(nums []int) [][]int {
 var result [][]int // 結果を記録する
 length := len(nums) // 配列の長さを求める
 if nums == nil || length < 3 {
 return result
 }
 sort.Ints(nums) //  
 for i := 0; i < length; i++ {
 // 現在の数字が0より大きい場合、3つの数字の和は0より大きくなければならないので、ループを終了する。
 if nums[i] > 0 {
 break
 }
 // 重複排除、添え字iの数
 if i > 0 && nums[i] == nums[i-1] {
 continue
 }
 l := i + 1
 r := length - 1
 for {
 if l >= r {
 break
 }
 sum := nums[i] + nums[l] + nums[r]
 if sum > 0 {
 r --
 continue
 }
 if sum < 0 {
 l ++
 continue
 }
 if sum == 0 {
 result = append(result, []int{nums[i], nums[l], nums[r]})
 // 重みをなくす、添え字をつける l
 for l < r && nums[l] == nums[l+1] {
 l++
 }
 // 重複排除、添え字r
 for l < r && nums[r] == nums[r-1] {
 r--
 }
 l++
 r--
 }
 }
 }
 return result
}
//java
class Solution {
 public static List<List<Integer>> threeSum(int[] nums) {
 List<List<Integer>> ans = new ArrayList();
 int len = nums.length;
 if(nums == null || len < 3) return ans;
 Arrays.sort(nums); //  
 for (int i = 0; i < len ; i++) {
 if(nums[i] > 0) break; // 現在の数字が0より大きい場合、3つの数字の和は0より大きくなければならないので、ループを終了する。
 if(i > 0 && nums[i] == nums[i-1]) continue; //  
 int L = i+1;
 int R = len-1;
 while(L < R){
 int sum = nums[i] + nums[L] + nums[R];
 if(sum == 0){
 ans.add(Arrays.asList(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 (sum < 0) L++;
 else if (sum > 0) R--;
 }
 } 
 return ans;
 }
}

念のため:

ここに示されたコードはLeetCodeを通して実行されました!

チャッターボックスにて

多くの人が良い習慣を身につけたいと願っていますが、ほとんどの人は3分間人間です。そのため、次のような計画を立てることにしました。

一緒にアルゴリズムを学び、ボーナスを受け取ってください!

参加様式:

また、多くの友人と「会う」こともできます。

団結し、共に学び、共に向上すること!

パンチカードのルールは

報酬

連続出勤1日につき $6.60の レッドパケットを私にご連絡ください!

連続出勤1日ごとに $16.60の レッドパケットをお渡しします!

66.60ドルの レッドパケットをご希望の方はご連絡ください!

個人的なエネルギーは十分ではありませんが、コンテンツは主に公開プラットフォームで公開され、他のプラットフォームは、タイムリーに更新されない場合があり、私は〜を許して願っています!

Read next

コンポーネント化されたデザイン思考

今、多くの人が原子設計を知っている、また、仕様設計にコンポーネントを知っているが、ただ単純な生産仕様は、より良い設計方法を考えるために多くの時間を作るには十分ではありません、優れた視覚的性能の基礎に焦点を当てる必要があり、徐々に注目のプロジェクトの相乗効果と体験的価値を強化し、徐々に新しいデザイン思考モードを形成します。 コンポーネント化されたデザイン思考は、機能性と視覚表現の要素を分解するプロセスです...

Feb 24, 2020 · 3 min read