全探索は「漏れなく、重複なく」

まず小さな制約で動く正解を作る。全探索はその基準になります。候補を列挙し、条件を確かめ、答えを更新します。

言語:Python / 計算量:O(N²)

前提:制約から計算量を見積もる

考え方

  1. 何を1候補とするか決めます。
  2. 組を選ぶなら i < j にして同じ組を2度数えません。
  3. 候補数と判定の計算量を掛けます。

具体例

[1,2,3] から和が4になる異なる2要素を選ぶと (1,3) の1組です。

実装

a = [1, 2, 3]
ans = 0
for i in range(len(a)):
    for j in range(i + 1, len(a)):
        if a[i] + a[j] == 4:
            ans += 1
print(ans)

注意する条件

i=j を許すか、順序を区別するかを先に確かめます。

確認問題

[1,2,3,4] で和5のペア i<j は何組?

解答と理由

2

(1,4) と (2,3) の2組です。

実装課題

N K と配列 A が2行。i<j かつ A_i+A_j=K の組数。1 ≤ N ≤ 100、0 ≤ A_i,K ≤ 200。

入力:
4 5
1 2 3 4
出力:
2
参考実装
n, k = map(int, input().split())
a = list(map(int, input().split()))
ans = 0
for i in range(n):
    for j in range(i + 1, n):
        ans += a[i] + a[j] == k
print(ans)

実戦につなげる補講

一度に全て読まなくて大丈夫です。今日は1節と1問から。

候補を列挙してから、判定を書く

候補の種類を1文にします。「異なる2つの添字」ならi<j。「各要素を選ぶ・選ばない」なら2^N通り。何を全探索するかが曖昧なままforを書き始めないようにします。

列挙の回数×1候補の判定コストが基本です。候補がN²通りでも、判定がsumでO(N)なら全体はO(N³)になります。

全探索は捨てずに、正しさの物差しにする

最初から速い式を思いつく必要はありません。小さい制約で動く愚直解を先に書くと、高速版と結果を比べられます。速いが間違った解法より、遅いが正しい解法の方が改善の出発点になります。

1変数を決めると、残りは計算で分かる?

合計がTになる2数を探すなら、xを決めたとき必要な相手はT−xです。全てのyを調べる代わりに、その値を調べる仕組みを作れます。ただし同じ要素を2回使うことや重複の数え方には注意します。

段階式の追加演習

1. 列挙の漏れを確認

添字0,1,2,3から異なる2個を選ぶ全組合せを列挙して。

ヒント

小さい方の添字を先に書く。

解答と理由

(0,1),(0,2),(0,3),(1,2),(1,3),(2,3)の6通り。

2. 判定コストを掛ける

全てのl,rについてsum(a[l:r])を計算する。なぜO(N²)ではない?

ヒント

列挙が二乗でも、1回のsumの長さは一定ではない。

解答と理由

区間が約N²個あり、長い区間の合計計算にN程度かかる。全区間長の総和はN(N+1)(N+2)/6なのでO(N³)。

3. 実装:一致する組

数列aの異なる2添字i<jで、a[i]+a[j]=targetとなる組数を返すcount_pairsを書いて。a=[2,2,5,8],target=10なら2。

ヒント

値が同じでも添字が違えば別要素。jはi+1から。

解答と理由

まずO(N²)の基準実装を作る。重複のある入力でも添字の組ごとに数えられる。

def count_pairs(a, target):
    answer = 0
    for i in range(len(a)):
        for j in range(i + 1, len(a)):
            if a[i] + a[j] == target:
                answer += 1
    return answer

4. 高速化の言語化

前の問題を大きいNに対応させたい。保存すると役立つ情報は?

ヒント

現在のxに必要な相手はtarget−x。過去に何個あったか。

解答と理由

過去の値の出現回数を辞書で保存する。現在の値を辞書へ追加する前に相手の個数を足すと、同じ添字の再利用と二重カウントを防げる。辞書の講義で実装する。

公式過去問への橋渡し

ABC143 D / 公式解説PDF

3要素の全探索から、2要素を固定して残りの候補数を境界で求める発想へ進む。

公式問題 / 公式解説

見本を閉じて確認

読了の記録・下書き・メモへ