Pythonで最も競争力の高い部分列を見つけるプログラム
問題の概要
配列 nums と整数 k が与えられたとき、nums からサイズ k の「最も競争力のある」部分列を求めます。ここで、ある部分列 s1 が同じサイズの別の部分列 s2 より競争力が高いとは、s1 と s2 が初めて異なる位置において、s1 の数値が s2 の対応する数値よりも小さいことを意味します。
例えば、入力が nums = [4,6,3,7]、k = 2 の場合、出力は [3,7] となります。サイズ 2 のすべての部分列 {[4,6], [4,3], [4,7], [6,3], [6,7], [3,7]} の中で、[3,7] が最も競争力の高い部分列だからです。
解法アプローチ:スタックを使った貪欲法
この問題は、スタックを利用した貪欲法(グリーディ法)で効率的に解くことができます。基本的な考え方は、「後から来るより小さい数と入れ替えられる限り、大きい数を削除していく」というものです。具体的な手順は以下の通りです。
- attempts(削除できる残り回数):= nums のサイズ − k
- stack := 空のリストを作成する
- nums の各要素 num に対して以下を繰り返す:
- stack が空でなく、num がスタックの先頭要素より小さく、attempts > 0 である間、スタックから要素を pop し、attempts を 1 減らす
- num をスタックに push する
- 最後に、スタックの先頭から k 個の要素を返す
このアルゴリズムの時間計算量は O(n) です。各要素は最大でも一度 push され、一度しか pop されないため、大きな入力サイズに対しても非常に高速に動作します。
実装例
理解を深めるために、以下のPythonコードを見てみましょう。
def solve(nums, k):
attempts = len(nums) - k
stack = []
for num in nums:
while stack and num < stack[-1] and attempts > 0:
stack.pop()
attempts -= 1
stack.append(num)
return stack[:k]
nums = [4,6,3,7]
k = 2
print(solve(nums, k))
入力
[4,6,3,7], 2
出力
[3,7]
このように、スタックを活用することで、全ての部分列を列挙せずとも線形時間で最も競争力の高い部分列を効率よく求めることができます。
-
Pythonで行列の転置を求めるプログラム
この記事では、与えられた問題に対する解法とアプローチについて詳しく解説します。 問題文 ある行列が与えられたとき、その転置を同じ行列に格納し、結果を表示する必要があります。 行列の転置とは、行を列に、列を行に入れ替えたものです。言い換えれば、行列Aの転置は、要素A[i][j]をA[j][i]と入れ替えることで得られます。 実装例 N = 4 def transpose(A): for i in range(N): for j in range(i+1, N): A[i][j], A[j][i] = A[j][i], A[i][j] # ドライ
-
Pythonで配列(リスト)の合計を求める方法をわかりやすく解説
この記事では、配列(リスト)の合計値を求めるという問題に対して、Pythonでの解決策とアプローチをわかりやすく解説します。 問題の定義 配列が入力として与えられたとき、その配列に含まれるすべての要素の合計を計算することを目標とします。 例えば、[1, 2, 3, 4, 5] という配列が与えられた場合、出力は 15 になります。 アプローチ1:ループを使った素朴な方法(総当たり法) 最も基本的な方法は、リストを先頭から順に走査し、各要素を合計用の変数に加算していくやり方です。手順は以下の通りです。 合計を格納する変数を 0 で初期化します。 for ループでリストの各要素を取り出し、順番に