Welcome to Subscribe On Youtube

Formatted question description: https://leetcode.ca/all/1908.html

1908. Game of Nim

Level

Medium

Description

Alice and Bob take turns playing a game with Alice starting first.

In this game, there are n piles of stones. On each player’s turn, the player should remove any positive number of stones from a non-empty pile of his or her choice. The first player who cannot make a move loses, and the other player wins.

Given an integer array piles, where piles[i] is the number of stones in the i-th pile, return true if Alice wins, or false if Bob wins.

Both Alice and Bob play optimally.

Example 1:

Input: piles = [1]

Output: true

*Explanation:8 There is only one possible scenario:

  • On the first turn, Alice removes one stone from the first pile. piles = [0].
  • On the second turn, there are no stones left for Bob to remove. Alice wins.

Example 2:

Input: piles = [1,1]

Output: false

Explanation: It can be proven that Bob will always win. One possible scenario is:

  • On the first turn, Alice removes one stone from the first pile. piles = [0,1].
  • On the second turn, Bob removes one stone from the second pile. piles = [0,0].
  • On the third turn, there are no stones left for Alice to remove. Bob wins.

Example 3:

Input: piles = [1,2,3]

Output: false

Explanation: It can be proven that Bob will always win. One possible scenario is:

  • On the first turn, Alice removes three stones from the third pile. piles = [1,2,0].
  • On the second turn, Bob removes one stone from the second pile. piles = [1,1,0].
  • On the third turn, Alice removes one stone from the first pile. piles = [0,1,0].
  • On the fourth turn, Bob removes one stone from the second pile. piles = [0,0,0].
  • On the fifth turn, there are no stones left for Alice to remove. Bob wins.

Constraints:

  • n == piles.length
  • 1 <= n <= 7
  • 1 <= piles[i] <= 7

Follow-up: Could you find a linear time solution?

Solution

For the game of Nim, where Alice starts first, Alice can win if and only if the bitwise xor results of all the elements in piles is not 0.

  • class Solution {
        public boolean nimGame(int[] piles) {
            int xor = 0;
            for (int pile : piles)
                xor ^= pile;
            return xor != 0;
        }
    }
    
  • class Solution {
    public:
        bool nimGame(vector<int>& piles) {
            unordered_map<int, int> memo;
            int p[8] = {1};
            for (int i = 1; i < 8; ++i) {
                p[i] = p[i - 1] * 8;
            }
            auto f = [&](vector<int>& piles) {
                int st = 0;
                for (int i = 0; i < piles.size(); ++i) {
                    st += piles[i] * p[i];
                }
                return st;
            };
            function<bool(vector<int>&)> dfs = [&](vector<int>& piles) {
                int st = f(piles);
                if (memo.count(st)) {
                    return memo[st];
                }
                for (int i = 0; i < piles.size(); ++i) {
                    for (int j = 1; j <= piles[i]; ++j) {
                        piles[i] -= j;
                        if (!dfs(piles)) {
                            piles[i] += j;
                            return memo[st] = true;
                        }
                        piles[i] += j;
                    }
                }
                return memo[st] = false;
            };
            return dfs(piles);
        }
    };
    
  • class Solution:
        def nimGame(self, piles: List[int]) -> bool:
            @cache
            def dfs(st):
                lst = list(st)
                for i, x in enumerate(lst):
                    for j in range(1, x + 1):
                        lst[i] -= j
                        if not dfs(tuple(lst)):
                            return True
                        lst[i] += j
                return False
    
            return dfs(tuple(piles))
    
    
  • func nimGame(piles []int) bool {
    	memo := map[int]bool{}
    	p := make([]int, 8)
    	p[0] = 1
    	for i := 1; i < 8; i++ {
    		p[i] = p[i-1] * 8
    	}
    	f := func(piles []int) int {
    		st := 0
    		for i, x := range piles {
    			st += x * p[i]
    		}
    		return st
    	}
    	var dfs func(piles []int) bool
    	dfs = func(piles []int) bool {
    		st := f(piles)
    		if v, ok := memo[st]; ok {
    			return v
    		}
    		for i, x := range piles {
    			for j := 1; j <= x; j++ {
    				piles[i] -= j
    				if !dfs(piles) {
    					piles[i] += j
    					memo[st] = true
    					return true
    				}
    				piles[i] += j
    			}
    		}
    		memo[st] = false
    		return false
    	}
    	return dfs(piles)
    }
    
  • function nimGame(piles: number[]): boolean {
        const p: number[] = Array(8).fill(1);
        for (let i = 1; i < 8; ++i) {
            p[i] = p[i - 1] * 8;
        }
        const f = (piles: number[]): number => {
            let st = 0;
            for (let i = 0; i < piles.length; ++i) {
                st += piles[i] * p[i];
            }
            return st;
        };
        const memo: Map<number, boolean> = new Map();
        const dfs = (piles: number[]): boolean => {
            const st = f(piles);
            if (memo.has(st)) {
                return memo.get(st)!;
            }
            for (let i = 0; i < piles.length; ++i) {
                for (let j = 1; j <= piles[i]; ++j) {
                    piles[i] -= j;
                    if (!dfs(piles)) {
                        piles[i] += j;
                        memo.set(st, true);
                        return true;
                    }
                    piles[i] += j;
                }
            }
            memo.set(st, false);
            return false;
        };
        return dfs(piles);
    }
    
    

All Problems

All Solutions