Python
 Computer >> コンピューター >  >> プログラミング >> Python

【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) であり、非常に効率的です。

  1. Pythonで二分木が二分探索木(BST)かどうかを判定する方法

    はじめに:BSTとは何か二分木が与えられたとき、それが二分探索木(Binary Search Tree:BST)であるかどうかを判定することは、データ構造の学習やコーディング面接でよく出題される定番の問題です。BSTには以下のような重要な性質があります。左部分木に含まれるすべてのノードの値は、現在のノードの値より小さい右部分木に含まれるすべてのノードの値は、現在のノードの値より大きいこれらの性質は、木の中のすべてのノードに対して再帰的に成り立つたとえば、次のような二分木を考えてみましょう。ルート:5左の子:1右の子:9(その左の子:7、さらに左の子:6・右の子:8/右の子:10)この場合、すべ

  2. 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、または