Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで3要素の合計がターゲット未満となるトリプレットの個数を数えるプログラム

問題の概要

数値のリスト nums と値 target が与えられたとき、nums[i] + nums[j] + nums[k] < target を満たすトリプレット(i < j < k)の個数を求めることを考えます。

例えば、入力が nums = [-2, 6, 4, 3, 8]target = 12 の場合、出力は 5 になります。条件を満たすトリプレットは以下の通りです。

  • [-2, 6, 4]
  • [-2, 6, 3]
  • [-2, 4, 3]
  • [-2, 4, 8]
  • [-2, 3, 8]

解法のアプローチ

すべての組み合わせを総当たりで調べると O(n³) の計算量が必要になりますが、ソート」と「2ポインタ(two-pointer)技法」を組み合わせることで、O(n²) まで計算量を抑えられます。

解くための手順は以下の通りです。

  1. リスト nums を昇順にソートする
  2. ans := 0 と初期化する
  3. n := nums のサイズとする
  4. i を 0 から n−1 までループする
    • k := n − 1 とする
    • j を i+1 から n−1 までループする
      • k > j かつ nums[i] + nums[k] + nums[j] >= target の間、k を 1 減らし続ける
      • j == k になったらループを抜ける
      • ans += k − j を加算する
  5. ans を返す

このアルゴリズムのポイントは、リストがソート済みであるため、jk の間に含まれるすべての要素 m について nums[i] + nums[j] + nums[m] < target が自動的に成り立つという点です。つまり、条件を満たす範囲の幅(k − j)を一度に数え上げることができ、個別の組み合わせをすべて列挙する必要がありません。

実装例

以下にPythonでの実装例を示します。

class Solution:
   def solve(self, nums, target):
      nums.sort()
      ans = 0
      n = len(nums)
      for i in range(n):
         k = n - 1
         for j in range(i + 1, n):
            while k > j and nums[i] + nums[k] + nums[j] >= target:
               k -= 1
            if j == k:
               break
            ans += k - j
      return ans

ob1 = Solution()
nums = [-2, 6, 4, 3, 8]
target = 12
print(ob1.solve(nums, target))

入力

[-2, 6, 4, 3, 8], 12

出力

5

まとめ

このように、ソートと2ポインタ技法を活用することで、3重ループによる総当たりよりも大幅に効率的に、合計がターゲット未満となるトリプレットの個数を求めることができます。同様の手法は「3Sum」系の問題全般に応用できるため、ぜひ覚えておきましょう。

  1. Pythonで二分木の合計がkとなるパスの数を数える方法

    問題の概要 二分木と値 k が与えられたとき、あるノードからその子孫へ向かうパスのうち、通過するノードの値の合計がちょうど k と一致するものがいくつ存在するかを求める問題です。 例えば、次のような二分木を考えてみましょう。 このとき k = 5 であれば、出力は 2 となります。条件を満たすパスは [2, 3] と [1, 4] の2つだからです。 解き方のアプローチ:累積和(prefix sum)の活用 この問題は「累積和(prefix sum)」というテクニックを使うことで、全ノードを一度だけ訪問する効率的なアルゴリズムとして解けます。考え方の手順は以下の通りです。 count:マッ

  2. 【Python入門】数値が素数かどうかを判定するプログラムの書き方

    この記事では、ユーザーが入力した数値(1より大きい整数)が素数かどうかを判定するPythonプログラムを紹介します。サンプルコードと実行結果、処理の流れを丁寧に解説しているので、Python初心者の方でも理解しやすい内容になっています。素数とは?素数とは、1より大きい正の整数のうち、約数が1とその数自身の2つしか存在しない数のことです。たとえば、2・3・5・7・11などは約数が1と自分自身だけであるため素数です。一方、4や6のように1と自分自身以外の約数を持つ数は「合成数」と呼ばれます。素数判定プログラムのサンプルコード# 入力された数値が素数かどうかを判定するPythonプログラム # ユ