【Python】キャンディー削除ゲームで先手プレイヤーが勝つかどうかを判定するプログラム
問題の概要
数値のリスト candies があるとします。あるプレイヤー(player1)が友人(player2)と対戦するゲームを行います。各ターンで、プレイヤーは「同じ値が隣り合っている2つのキャンディー」を選んで取り除くことができます。そして、キャンディーを取り除けなくなった方の負けです。player1が先手であるとき、player1が勝利するかどうかを判定してください。
例えば、入力が nums = [2, 2, 5] の場合、出力は True になります。player1が先に「2」のペアを取り除けば、残った [5] からは相手が何も取り除けなくなるためです。
解法のアプローチ
この問題の鍵となるのは、「取り除けるペアの総数」はプレイヤーの戦略に関係なく一定だという点です。そこで、スタックを使って隣接する同じ値のペアを数え、その手数(turns)が奇数であれば先手のplayer1が最後の一手を打てるので勝ち、偶数であれば負けると判定できます。
具体的な手順は以下の通りです。
stack(スタック)を新しく作成する
turns(手数)を 0 で初期化する
nums の各要素 num について以下を繰り返す
スタックが空でなく、スタックのトップが num と同じ値の場合
スタックからポップする
turns を 1 増やす
それ以外の場合
num をスタックにプッシュする
turns が奇数なら true を、偶数なら false を返す
実装例
class Solution: def solve(self, nums): stack = [] turns = 0 for num in nums: if stack and stack[-1] == num: stack.pop() turns += 1 else: stack.append(num) return bool(turns & 1) ob = Solution() nums = [2, 2, 5] print(ob.solve(nums))
入力
[2, 2, 5]
出力
True
コードのポイント
戻り値の bool(turns & 1) は、ビット演算 AND を使って turns の奇偶を判定しています。turns が奇数(最下位ビットが1)の場合に True となり、先手のplayer1の勝利を意味します。このアルゴリズムの計算量は O(n)、空間計算量も O(n) であり、非常に効率的です。
-
Pythonで二分木が二分探索木(BST)かどうかを判定する方法
はじめに:BSTとは何か二分木が与えられたとき、それが二分探索木(Binary Search Tree:BST)であるかどうかを判定することは、データ構造の学習やコーディング面接でよく出題される定番の問題です。BSTには以下のような重要な性質があります。左部分木に含まれるすべてのノードの値は、現在のノードの値より小さい右部分木に含まれるすべてのノードの値は、現在のノードの値より大きいこれらの性質は、木の中のすべてのノードに対して再帰的に成り立つたとえば、次のような二分木を考えてみましょう。ルート:5左の子:1右の子:9(その左の子:7、さらに左の子:6・右の子:8/右の子:10)この場合、すべ
-
Pythonで与えられたグラフが2部グラフかどうかを判定するプログラム
2部グラフとは無向グラフが与えられたとき、そのグラフが2部グラフ(バイパータイトグラフ)であるかどうかを判定する方法を解説します。2部グラフとは、グラフのすべての頂点を2つの集合 A と B に分割でき、グラフ内のすべての辺 {u, v} が必ず一方の端点 u が集合 A、もう一方の端点 v が集合 B に属するようなグラフのことです。つまり、同じ集合内の頂点同士を結ぶ辺(A-A や B-B)が一切存在しないグラフです。例として、次のようなグラフを考えてみましょう。この場合、頂点 [0, 4] を集合 A に、[1, 2, 3] を集合 B に分類できます。すべての辺は A から B、または