1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

《アルゴリズムを学ぶ》12.全探索

Last updated at Posted at 2025-03-08

Overview

全探索(Brute Force Search) とは、すべての可能性を力ずくで試すアルゴリズム。
1.選択ソートの基本
2.選択ソートの特徴
3.典型問題を解いてみる

1. 全探索のパターン

探索方法 説明 使用例
1重ループ リストを1回スキャンする 最大値、最小値探索
2重ループ すべてのペアを調べる 2つの和が条件を満たすペア探索
3重ループ すべての3つ組を調べる 3つの和が条件を満たす組み合わせ探索
再帰的全探索(バックトラッキング) 状態を保持しながら再帰で探索 パス探索、ナップサック問題
ビット全探索 すべての部分集合を試す すべての組み合わせを列挙

2. 1重ループを使った全探索

リストの中から 最大値 を求める。

arr = [3, 1, 4, 1, 5, 9]
max_value = -float('inf')

for num in arr:
    max_value = max(max_value, num)

print(max_value)  # 9

ポイント:
・$O(N)$ でリスト全体を探索する
・最適化せずにシンプルに実装するのが全探索の基本

3. 2重ループを使った全探索

(1) すべてのペアを探索

arr = [1, 3, 5, 7]
for i in range(len(arr)):
    for j in range(i + 1, len(arr)):
        print(arr[i], arr[j])

ポイント:
・2つの要素の組み合わせを総当たりで試す
・$O(N²)$の計算量になる

(2) 指定の条件を満たすペアを探す

例: 数列 A の中で、A[i] + A[j] = X となる (i, j) のペアを探す。

A = [1, 2, 3, 4, 5]
X = 6

for i in range(len(A)):
    for j in range(i + 1, len(A)):
        if A[i] + A[j] == X:
            print(f"Pair: {A[i]}, {A[j]}")

ポイント:
・2重ループでペアをすべて試す
・より効率的な方法(ハッシュセットを使う)と比較できる

4. 3重ループを使った全探索

例: $A[i] + A[j] + A[k] = X$ となる (i, j, k) の組み合わせを探す。

A = [1, 2, 3, 4, 5]
X = 6

for i in range(len(A)):
    for j in range(i + 1, len(A)):
        for k in range(j + 1, len(A)):
            if A[i] + A[j] + A[k] == X:
                print(f"Triplet: {A[i]}, {A[j]}, {A[k]}")

ポイント:
・3重ループで全パターンを探索
・$O(N³)$の計算量になるが、小さなデータセットなら問題ない

5. ビット全探索

例: N 個の要素のすべての部分集合を列挙する。

A = [1, 2, 3]
N = len(A)

for bit in range(1 << N):  # 2^N 通りの部分集合
    subset = [A[i] for i in range(N) if bit & (1 << i)]
    print(subset)

ポイント:
・すべての部分集合を列挙
・$O(2^N)$の計算量なので N ≤ 20 程度まで

6. 典型問題を解いてみる

例題1. 2つの和が条件を満たすペア

問題: N 個の整数が与えられる。A[i] + A[j] = X となる (i, j) のペアが存在するか判定せよ。

参考: ABC315 B - Find Pair Sum

回答 
N, X = map(int, input().split())
A = list(map(int, input().split()))

for i in range(N):
    for j in range(i + 1, N):
        if A[i] + A[j] == X:
            print("Yes")
            exit()
print("No")

例題2. 3つの和が条件を満たす組み合わせ

問題: N 個の整数が与えられる。A[i] + A[j] + A[k] = X となる (i, j, k) の組み合わせを探せ。

参考: ABC318 B - Find Triplet Sum

回答 
N, X = map(int, input().split())
A = list(map(int, input().split()))

for i in range(N):
    for j in range(i + 1, N):
        for k in range(j + 1, N):
            if A[i] + A[j] + A[k] == X:
                print(A[i], A[j], A[k])

例題3. ビット全探索

問題: N 個の整数から、すべての部分集合の和を出力せよ。

参考: ABC319 C - Subset Sum

回答 
N = int(input())
A = list(map(int, input().split()))

for bit in range(1 << N):
    subset_sum = sum(A[i] for i in range(N) if bit & (1 << i))
    print(subset_sum)

例題4. 文字列の全探索

問題: 長さ N の文字列 S が与えられる。S に "abc" が含まれるか判定せよ。

参考: ABC320 B - Find Substring

回答 
S = input()
N = len(S)

for i in range(N - 2):
    if S[i:i+3] == "abc":
        print("Yes")
        exit()
print("No")
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?