Pythonで石を渡って川を越えられるか判定するプログラム
ソートされた整数リスト stones が与えられ、これは渡ろうとしている川に置かれた石の位置を表しているとします。川を渡り切るためには、必ず最後の石までたどり着かなければなりません。各ステップでは、直前のジャンプ距離を k としたとき、(k − 1, k, k + 1) のいずれかの距離だけ前へジャンプすることができます。この条件のもとで、川を渡ることが可能かどうかを判定するのが本問題です。
問題の例
たとえば入力が stones = [0, 1, 3, 4, 5, 6, 8, 9, 13] の場合、答えは True になります。位置 0 からスタートし、まず 1 単位ジャンプして石 1 へ、次に 2 単位ジャンプして石 3 へ、さらに 2 単位で石 5 へ、続いて 3 単位で石 8 へ、最後に 5 単位ジャンプして最後の石である 13 に到達できるからです。
解法のアプローチ
この問題は、深さ優先探索(DFS)によるバックトラッキングで効率よく解けます。手順は以下の通りです。
start := A[0]、end := Aの最後の要素とするAを一意な要素のみを持つ集合(set)に変換し、位置の存在確認を高速に行えるようにする- 関数
check()を定義する。初期値はpos := start、prev := 0 posがendと等しければTrueを返す- [prev − 1, prev, prev + 1] の各
jumpに対して以下を試すjump >= 1であれば、next_pos := jump + posを計算するnext_posがAに存在し、かつcheck(next_pos, jump)が真であればTrueを返す
- どのジャンプでもゴールに届かなければ
Falseを返す - メイン処理から
check()を呼び出し、その結果を返す
重要なポイントは、ジャンプできる距離が直前のジャンプ距離に依存するため、現在位置だけでなく直前のジャンプ距離も再帰の状態として引き継ぐ必要がある点です。また、ジャンプ距離は最低 1 以上でなければならないため、jump >= 1 のチェックを忘れないようにしましょう。
Python 実装例
それでは、実際のコードを見て理解を深めましょう。
class Solution: def solve(self, A): start, end = A[0], A[-1] A = set(A) def check(pos=start, prev=0): if pos == end: return True for jump in [prev - 1, prev, prev + 1]: if jump >= 1: next_pos = jump + pos if next_pos in A and check(next_pos, jump): return True return False return check() ob = Solution() stones = [0, 1, 3, 4, 5, 6, 8, 9, 13] print(ob.solve(stones))
入力
[0, 1, 3, 4, 5, 6, 8, 9, 13]
出力
True
計算量と改善のヒント
この実装では、「現在位置」と「直前のジャンプ距離」の組み合わせを状態として再帰的に探索します。石の数を n とすると、最悪の場合の時間計算量は O(n²) 程度になります。より大規模な入力に対応するには、一度訪れた (位置, ジャンプ距離) の組み合わせを辞書などでキャッシュするメモ化を追加すると、無駄な再探索を排除でき、パフォーマンスが大きく向上します。コーディング面接や競技プログラミングでは、この最適化まで言及できると好印象です。
-
【Python入門】数値が素数かどうかを判定するプログラムの書き方
この記事では、ユーザーが入力した数値(1より大きい整数)が素数かどうかを判定するPythonプログラムを紹介します。サンプルコードと実行結果、処理の流れを丁寧に解説しているので、Python初心者の方でも理解しやすい内容になっています。素数とは?素数とは、1より大きい正の整数のうち、約数が1とその数自身の2つしか存在しない数のことです。たとえば、2・3・5・7・11などは約数が1と自分自身だけであるため素数です。一方、4や6のように1と自分自身以外の約数を持つ数は「合成数」と呼ばれます。素数判定プログラムのサンプルコード# 入力された数値が素数かどうかを判定するPythonプログラム # ユ
-
Pythonで文字列が回文(パリンドローム)かどうかを判定する方法
文字列が与えられたとき、その文字列が回文(パリンドローム)であるかどうかを判定するのが、本記事の目的です。 回文とは、「madam」「level」「しんぶんし」のように、前から読んでも後ろから読んでも同じになる文字列のことを指します。Pythonでは、スライス記法を使うことで、わずか数行のコードでこの判定を実装できます。 アルゴリズム Step1: 文字列を入力として受け取る。 Step2: スライスを使って文字列を逆順にし、元の文字列と比較する。 Step3: 判定結果を表示する。 ポイント解説:スライスによる文字列の反転 このプログラムの核心は [::-1] というスライス記法です。こ