Pythonでターゲット配列を形成するための部分配列の最小増分回数を求めるプログラム
問題の概要
正の値からなる配列 target が与えられているとします。また、同じサイズで、すべての要素が0である配列 initial も用意します。このとき、次の操作を繰り返して initial を target に一致させるために必要な最小の操作回数を求めます。
操作の定義: initial から任意の部分配列(連続する区間)を選び、その範囲内の各要素の値を1ずつ増やします。
具体例
入力が target = [2,3,4,3,2] の場合、出力は 4 になります。手順は以下の通りです。
- 最初、配列は [0,0,0,0,0] です。
- インデックス0〜4を選んで1増やす → [1,1,1,1,1]
- 再びインデックス0〜4を選んで1増やす → [2,2,2,2,2]
- インデックス1〜3を選んで1増やす → [2,3,3,3,2]
- 最後にインデックス2を選んで1増やす → [2,3,4,3,2](ターゲットと一致)
合計4回の操作でターゲット配列が完成しました。
解法のアプローチ
この問題は、隣接する要素間の差に着目することで効率的に解けます。配列を左から右へ走査し、現在の値が前の値よりも大きい場合、その差の分だけ新たな操作を開始する必要があります。逆に、値が減少するか同じ場合は、すでに進行中の操作でカバーできるため、追加の操作は不要です。
prev_num := 0(直前の要素の値。初期値は0)steps := 0(操作回数のカウンタ)- target 内の各
valについて以下を繰り返します。val > prev_numの場合:steps += val - prev_num、それ以外は何もしないprev_num := valとして更新
- 最後に
stepsを返します。
実装例
以下のPythonコードで理解を深めましょう。
def solve(target): prev_num = 0 steps = 0 for val in target: steps += val - prev_num if val > prev_num else 0 prev_num = val return steps target = [2,3,4,3,2] print(solve(target))
入力
[2,3,4,3,2]
出力
4
計算量について
このアルゴリズムは配列を一度だけ走査するため、時間計算量は O(n)、追加の記憶領域は O(1) で済みます。非常にシンプルかつ効率的な解法と言えるでしょう。
-
Pythonで色のマージ後に残る最小個数を求めるプログラム
問題概要 赤(R)、緑(G)、青(B)の3種類の色からなるリストを考えます。隣り合う異なる2つの色は、残りの「第3の色」1個に変換(マージ)できます。この変換を好きな順序で何度でも繰り返してよいとき、最終的に残る要素数の最小値を求めるのがこの問題です。 たとえば入力が colors = [G, R, G, B, R] の場合、次のように変換を進めることで最終的に1個まで減らせます。したがって出力は 1 となります。 解き方のアプローチ 一見すると状態探索が必要そうな問題ですが、実はXOR(排他的論理和)を使ったシンプルな判定だけで答えが求まります。手順は以下の通りです。 n := 色リス
-
Pythonで合計がnとなるフィボナッチ数の最小個数を求めるプログラム
問題の概要ある整数 n が与えられたとき、その合計がちょうど n になるようにするために必要なフィボナッチ数の最小個数を求めます。たとえば、入力が n = 20 の場合、出力は 3 になります。これは、フィボナッチ数列に含まれる [2, 5, 13] の3つの数を足し合わせることで 20 を作れるためです。解決のためのアルゴリズムこの問題は「貪欲法(グリーディ法)」を用いることで効率的に解けます。基本的な考え方は、「n 以下の最大のフィボナッチ数を選び、n から引く」という操作を n が 0 になるまで繰り返すというものです。res := 0(使用したフィボナッチ数のカウント用変数)fibo