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

Pythonで「すべてのペアが互いに割り切れる」最大サブセットのサイズを求めるプログラム

問題の概要

重複しない数値のリスト nums が与えられたとします。このとき、サブセット内の任意の2つの要素のペア (i, j) について、「i % j = 0」または「j % i = 0」のどちらかが必ず成り立つような最大のサブセットを見つけ、そのサイズを返すのが目的です。

例えば、入力が nums = [3, 6, 12, 24, 26, 39] の場合、出力は 4 となります。これは、最大の有効なサブセットが [3, 6, 12, 24] になるためです(3 → 6 → 12 → 24 と、すべての隣接する要素同士が割り切れる関係になっています)。

解法の考え方(動的計画法)

この問題は、動的計画法(DP)を使うことで効率的に解くことができます。基本的な発想は「最長増加部分列(LIS)」と似ています。

  • リストを昇順にソートしておくことで、ある要素より前の要素だけを約数候補としてチェックすればよくなります。
  • dp[i] を「nums[i] を末尾とする有効なサブセットの最大サイズ」と定義します。初期値はすべて 1 です(自分自身だけで構成される場合)。
  • i より小さい各 j について nums[i] % nums[j] == 0(割り切れる)ならば、dp[i] = max(dp[i], dp[j] + 1) で更新できます。

アルゴリズムの手順

  • dp:リスト nums と同じサイズの配列を作り、すべて 1 で初期化します。
  • リスト nums を昇順にソートします。
  • n:リストのサイズを取得します。
  • n <= 1 の場合はそのまま n を返します。
  • ans を 0 で初期化します。
  • i を 1 から n 未満まで繰り返し:
    • j を 0 から i 未満まで繰り返し:
      • nums[i]nums[j] で割り切れる場合、dp[i]dp[i]dp[j] + 1 の大きい方で更新します。
    • ansansdp[i] の大きい方で更新します。
  • 最後に ans を返します。

Pythonでの実装例

以下が実際の実装コードです。

class Solution:
   def solve(self, nums):
      dp = [1] * len(nums)
      nums.sort()
      n = len(nums)
      if n <= 1:
         return n
      ans = 0
      for i in range(1, n):
         for j in range(0, i):
            if nums[i] % nums[j] == 0:
            dp[i] = max(dp[i], dp[j] + 1)
         ans = max(ans, dp[i])
      return ans
ob = Solution()
nums = [3, 6, 12, 24, 26, 39]
print(ob.solve(nums))

入力

[3, 6, 12, 24, 26, 39]

出力

4

計算量について

このアルゴリズムの時間計算量は二重ループにより O(n²) です(n はリストの要素数)。空間計算量はDP配列分の O(n) となります。ソートを行うことで、割り切れる関係の判定を前方の要素に限定でき、正しくDPを適用できるのがポイントです。


  1. Pythonで配列内の最大の要素を見つける方法を解説

    この記事では、「配列の中から最大の要素を求める」という問題の解決方法について詳しく解説します。 問題の概要 問題文:与えられた配列に対して、その中で最も大きい要素を計算して求める必要があります。 ここではブルートフォース(総当たり)アプローチを使用します。これは、配列全体を先頭から順番に走査しながら各要素を比較し、その時点での最大値を更新していくというシンプルかつ確実な手法です。 実装例 以下に具体的なコードを示します。 # 最大値を求める関数 def largest(arr, n): # 最大要素の初期値として最初の要素を設定 max = arr[0] # 配列全体を

  2. Pythonで配列内の最大要素を見つける方法【初心者向け解説】

    本記事では、配列の中から最大の要素を見つけるための解法とアプローチについて詳しく解説します。 問題の概要 配列が入力として与えられたとき、その中から最も大きい要素を見つけ出すことが課題となります。 アプローチ この問題は「線形探索」と呼ばれるシンプルな手法で解決できます。手順は以下の通りです。 まず、変数 max を配列の最初の要素で初期化します。 次に、2番目の要素から配列の末尾まで順番に走査していきます。 走査中の各要素について、現在の max の値と比較します。 要素が max より大きければ、max の値をその要素で更新します。 そうでなければ、そのまま次の要素へ進みます。 この処