C - 連続カード分け / Consecutive Card Distribution 解説 by admin
Gemini 3.0 Flash (Thinking)概要
\(N\) 枚の異なる整数が書かれたカードを、昇順に並べたときに値が \(1\) ずつ増加する「連番グループ」に分けるとき、最小で何個のグループが必要かを求める問題です。
考察
この問題を解くための重要なポイントは、「カードをどのような順番で並べても、最終的なグループ分けには影響しない」という点です。したがって、まずはカードを昇順にソートして考えるのが自然です。
例えば、カードが \(\{3, 5, 4, 8, 7\}\) のとき、これらをソートすると \(\{3, 4, 5, 7, 8\}\) となります。 - \(3\) と \(4\) は連続している(差が \(1\))ので、同じグループに入れられます。 - \(4\) と \(5\) も連続している(差が \(1\))ので、同じグループに入れられます。 - \(5\) と \(7\) は連続していない(差が \(2\))ため、どうしてもここでグループを分けなければなりません。 - \(7\) と \(8\) は連続している(差が \(1\))ので、同じグループに入れられます。
結果として、\(\{3, 4, 5\}\) と \(\{7, 8\}\) の \(2\) つのグループに分けるのが最適(最小)であることがわかります。
つまり、ソート済みの配列において「隣り合う要素の差が \(1\) ではない箇所」がいくつあるかを数えることで、必要なグループの数を特定できます。新しいグループが必要になるのは、常に「前のカードと値が連続していないカード」が現れたタイミングです。
アルゴリズム
- 与えられた \(N\) 枚のカードの数値 \(A_i\) を配列に格納し、昇順にソートします。
- グループ数のカウント(
ans)を \(1\) に初期化します(カードが \(1\) 枚以上あれば、最低でも \(1\) つのグループは存在するため)。 - 配列を先頭から走査し、隣り合う要素 \(A_i\) と \(A_{i+1}\) を比較します。
- もし \(A_{i+1} \neq A_i + 1\) であれば、値が連続していないため、
ansを \(1\) 加算します。 - 最終的な
ansの値を出力します。
計算量
- 時間計算量: \(O(N \log N)\)
- カードのソートに \(O(N \log N)\) かかります。
- その後の配列の走査は \(O(N)\) です。
- 全体としてソートの計算量が支配的になりますが、\(N = 2 \times 10^5\) であれば制限時間内に十分間に合います。
- 空間計算量: \(O(N)\)
- 入力された \(N\) 枚のカードを保持するために \(O(N)\) のメモリを使用します。
実装のポイント
高速な入出力: Pythonの場合、
sys.stdin.read().split()を使うことで、大量の入力を一括で読み込むことができ、実行時間の短縮につながります。隣り合う要素の比較: ループの範囲を \(N-1\) までに設定し、
A[i]とA[i+1]を比較することで、配列の範囲外参照を防ぎながら正しく判定できます。ソースコード
import sys
def main():
# 標準入力からすべてのデータを取得し、空白(スペースや改行)で分割してリストにする
# この方法は大量の入力を高速に読み込むのに適しています
input_data = sys.stdin.read().split()
# 入力が空の場合は何もせず終了
if not input_data:
return
# 最初の値がカードの枚数 N
n = int(input_data[0])
# 残りの値が各カードに書かれた整数 A_i
# 整数型のリストに変換する
a = list(map(int, input_data[1:]))
# カードに書かれた整数を昇順にソートする
# 連番グループを特定しやすくするため
a.sort()
# カードが0枚の場合はグループ数も0(制約上は 1 <= N)
if n == 0:
print(0)
return
# 最小のグループ数を求める
# ソートされた状態で、隣り合う要素の差が1でない箇所があるたびに
# 新しいグループが必要になる
ans = 1
for i in range(n - 1):
# 隣り合う整数の差が1でない場合、そこは連番ではない
if a[i+1] != a[i] + 1:
ans += 1
# 結果を出力する
print(ans)
if __name__ == '__main__':
main()
この解説は gemini-3-flash-thinking によって生成されました。
投稿日時:
最終更新: