【Python】合計がpで割り切れるようにする最小の部分配列を求める方法
問題の概要
配列 nums と整数 p が与えられたとき、「残りの要素の合計が p で割り切れる」状態を作るために、最小の部分配列(ただし配列全体は削除しない)を取り除くことを考えます。求めたいのは削除すべき最小の部分配列の長さであり、そのような部分配列が存在しない場合は -1 を返します。
例えば、nums = [8,2,6,5,3]、p = 7 の場合を考えてみましょう。このとき出力は 1 になります。なぜなら、末尾の要素「3」を削除すれば残りの合計は 21 となり、21 は 7 で割り切れるからです。
解法のアイデア:累積和と剰余の活用
この問題は、累積和(プレフィックスサム)の剰余を利用することで効率的に解けます。ある区間 [i+1, j] を削除したとき、残りの合計が p で割り切れるという条件は、「j 番目までの累積和の剰余」と「i 番目までの累積和の剰余」の差が、配列全体の合計の剰余 s と一致すると言い換えられます。各剰余が最後に現れた位置を辞書に記録しておけば、配列を一度走査するだけで答えが求まります。
アルゴリズムの手順
- ans := 無限大(答えの初期値)
- s := nums の全要素の合計を p で割った余り
- d := {0: -1} というキーと値のペアを持つ辞書(マップ)
- cum := 0(累積和)
- s が 0 と等しい場合は、そのまま 0 を返す(既に条件を満たしているため)
- i を 0 から nums のサイズ未満まで繰り返す:
- cum := cum + nums[i]
- r := cum を p で割った余り
- (r - s) mod p が d に存在する場合:
- ans := ans と (i - d[(r-s) mod p]) の小さい方
- d[r] := i
- ans が nums のサイズより小さければ ans を、そうでなければ -1 を返す
Pythonでの実装例
それでは、実際のコードを見て理解を深めましょう。
def solve(nums, p):
ans = float("inf")
s = sum(nums) % p
d = {0:-1}
cum = 0
if s == 0:
return 0
for i in range(len(nums)):
cum += nums[i]
r = cum % p
if (r-s) % p in d:
ans = min(ans, i-d[(r-s)%p])
d[r] = i
return ans if ans<len(nums) else -1
nums = [8,2,6,5,3]
p = 7
print(solve(nums, p))入力
[8,2,6,5,3], 7
出力
1
コードのポイント
このアルゴリズムの計算量は O(n)、必要な追加メモリは O(min(n, p)) であり、全ての部分配列を調べる総当たり法(O(n²))よりも大幅に効率的です。辞書 d には各剰余が最後に現れたインデックスを保存するため、常に「最も短くなる削除区間」を正しく検出できます。また、初期値 {0: -1} を入れておくことで、配列の先頭から削除するケースも漏れなく処理できる点が重要です。
-
Pythonですべての連続する部分配列の合計を求めるプログラム
問題概要数値のリスト nums が与えられたとき、その中のすべての連続する部分配列(サブリスト)を考えます。それぞれの部分配列の合計を計算し、さらにそれらの総和を求めます。最後に、結果を 10 ** 9 + 7(1,000,000,007)で割った余りを返します。例えば、入力が nums = [3, 4, 6] の場合、出力は 43 になります。考えられる部分配列は以下の通りです。[3][4][6][3, 4][4, 6][3, 4, 6]これらすべての合計を足すと 3 + 4 + 6 + 7 + 10 + 13 = 43 となります。解法のアプローチすべての部分配列を実際に生成して合計を計算
-
Pythonでインドの国旗を描く方法!NumPyとMatplotlibを使った完全ガイド
Pythonのグラフ描画ライブラリは非常に多機能で、単なるデータの可視化にとどまらず、国旗のような図形も自由に描くことができます。その意味で、これらのモジュールには芸術的な一面もあると言えるでしょう。この記事では、numpyとmatplotlibというライブラリを使って、インドの国旗を描く方法をわかりやすく解説します。 インド国旗の構成要素 インドの国旗は、上から順にサフラン(オレンジ)、白、緑の3本の横帯で構成され、中央には24本のスポークを持つ紺色の車輪「アショーカ・チャクラ」(法輪)が描かれています。各要素には次のような意味が込められています。 サフラン(オレンジ):勇気と自己犠牲