questions C

This commit is contained in:
2025-05-25 10:16:13 +01:00
parent 1e0aebfbfd
commit e6a22f98f8
85 changed files with 16925 additions and 0 deletions

View File

@@ -0,0 +1,151 @@
title: Chalkboard XOR Game
slug: chalkboard-xor-game
difficulty: hard
leetcode_id: 810
leetcode_url: https://leetcode.com/problems/chalkboard-xor-game/
categories:
- arrays
- math
patterns:
- greedy
description: |
You are given an array of integers `nums` representing the numbers written on a chalkboard.
Alice and Bob take turns erasing exactly one number from the chalkboard, with Alice starting first. If erasing a number causes the bitwise XOR of all the elements of the chalkboard to become `0`, then that player loses. The bitwise XOR of one element is that element itself, and the bitwise XOR of no elements is `0`.
Also, if any player starts their turn with the bitwise XOR of all the elements of the chalkboard equal to `0`, then that player wins.
Return `true` *if and only if Alice wins the game, assuming both players play optimally*.
constraints: |
- `1 <= nums.length <= 1000`
- `0 <= nums[i] < 2^16`
examples:
- input: "nums = [1,1,2]"
output: "false"
explanation: "Alice has two choices: erase 1 or erase 2. If she erases 1, nums becomes [1, 2] with XOR = 3. Bob can then force Alice to erase the last element and lose. If Alice erases 2, nums becomes [1, 1] with XOR = 0, so Alice loses immediately."
- input: "nums = [0,1]"
output: "true"
explanation: "Alice can erase 1, leaving [0]. The XOR is 0, but it was already non-zero before her move completed, and now Bob faces XOR = 0 at the start of his turn, so Bob loses."
- input: "nums = [1,2,3]"
output: "true"
explanation: "XOR of [1,2,3] = 0. Alice starts with XOR = 0, so she wins immediately."
explanation:
intuition: |
This problem looks like it requires game simulation or minimax, but there's a beautiful mathematical insight that reduces it to a simple formula.
Think about XOR properties: if the XOR of all elements is already `0` when it's your turn, you win. The key insight is understanding *when* Alice can be forced into a losing position.
Alice loses only if **every** number she could erase would make the XOR become `0`. Let's think about when this happens. If the current XOR is `X ≠ 0`, and Alice must pick a number `nums[i]` such that `X XOR nums[i] = 0`, then `nums[i] = X`. This means Alice loses only if **all** remaining numbers equal the current XOR value — which means all numbers are identical.
But here's the clever part: if all `n` numbers are identical (say, all equal to `v`), then:
- If `n` is even: XOR = `v XOR v XOR ... = 0`, so Alice wins immediately
- If `n` is odd: XOR = `v`, and Alice must erase `v`, leaving an even count where Bob faces XOR = 0 and wins
Generalising this: Alice loses only when forced to make XOR = 0. With an even number of elements and non-zero XOR, Alice can always find a "safe" move (at least one element whose removal doesn't make XOR = 0). This is because if removing **any** element made XOR = 0, all elements would need to equal the current XOR, making them all identical — but then with even count, XOR would already be 0.
Therefore: **Alice wins if and only if the initial XOR is 0, OR the array has an even length.**
approach: |
The solution is remarkably simple once you understand the game theory:
**Step 1: Calculate the XOR of all elements**
- Compute `xor_sum` by XORing all elements in `nums`
- This tells us the starting game state
&nbsp;
**Step 2: Check the two winning conditions for Alice**
- **Condition 1:** If `xor_sum == 0`, Alice wins immediately (she starts with XOR = 0)
- **Condition 2:** If `len(nums)` is even, Alice wins (she can always find a safe move)
&nbsp;
**Step 3: Return the result**
- Return `True` if either condition is met, `False` otherwise
- This covers all cases: Alice wins if she starts with XOR = 0, or if she has an even number of elements to work with
&nbsp;
The mathematical proof: with even length and non-zero XOR, if removing any element made XOR = 0, then each element `nums[i]` would equal the total XOR. But `n` identical values XORed together (with `n` even) gives 0, contradicting our assumption that XOR ≠ 0.
common_pitfalls:
- title: Attempting Game Simulation
description: |
A natural first instinct is to simulate the game using recursion or dynamic programming, trying all possible moves for both players.
With up to 1000 elements, this approach has exponential complexity — the game tree branches at each turn, leading to `O(n!)` possibilities. This will cause **Time Limit Exceeded**.
The key is recognising this as a **mathematical problem** with a closed-form solution, not a search problem.
wrong_approach: "Recursive simulation with memoisation"
correct_approach: "Use XOR properties and parity analysis"
- title: Forgetting the Even-Length Guarantee
description: |
Some solutions correctly check if XOR = 0 but miss the even-length winning condition.
The insight is subtle: with an even number of elements and non-zero XOR, Alice can *always* find at least one element whose removal doesn't make XOR = 0. This is guaranteed by the pigeonhole principle applied to XOR values.
wrong_approach: "Only checking if initial XOR is 0"
correct_approach: "Check both XOR = 0 and even length conditions"
- title: Misunderstanding the Winning Condition
description: |
The rules have a subtle distinction:
- If you **start** your turn with XOR = 0, you **win**
- If your move **causes** XOR to become 0, you **lose**
These are different! Starting with XOR = 0 is an immediate win, not a loss. This catches players who think XOR = 0 is always bad.
wrong_approach: "Thinking XOR = 0 means current player loses"
correct_approach: "XOR = 0 at turn start means win; causing XOR = 0 means loss"
key_takeaways:
- "**Game theory simplification**: Many two-player games have elegant mathematical solutions — look for invariants and parity arguments before attempting simulation"
- "**XOR properties**: XOR of identical values cancels out (even count = 0), which drives the parity-based solution"
- "**Constraint analysis**: The even-length guarantee comes from a proof by contradiction using XOR algebra"
- "**Pattern recognition**: This problem teaches that 'hard' brainteasers often have O(n) or O(1) solutions hiding behind the complexity"
time_complexity: "O(n). We traverse the array once to compute the XOR of all elements."
space_complexity: "O(1). We only use a single variable (`xor_sum`) regardless of input size."
solutions:
- approach_name: XOR and Parity Check
is_optimal: true
code: |
def xor_game(nums: list[int]) -> bool:
# Calculate XOR of all elements
xor_sum = 0
for num in nums:
xor_sum ^= num
# Alice wins if:
# 1. XOR is already 0 (she wins immediately), OR
# 2. Array has even length (she can always find a safe move)
return xor_sum == 0 or len(nums) % 2 == 0
explanation: |
**Time Complexity:** O(n) — Single pass to compute XOR.
**Space Complexity:** O(1) — Only one integer variable used.
The solution uses game theory insight: Alice wins if she starts with XOR = 0, or if she has an even number of elements (guaranteeing a safe move exists). This elegant formula avoids expensive game tree simulation.
- approach_name: One-Liner with Reduce
is_optimal: true
code: |
from functools import reduce
from operator import xor
def xor_game(nums: list[int]) -> bool:
# XOR all elements; Alice wins if result is 0 or length is even
return reduce(xor, nums) == 0 or len(nums) % 2 == 0
explanation: |
**Time Complexity:** O(n) — Reduce iterates through all elements.
**Space Complexity:** O(1) — No additional space beyond the accumulator.
A more Pythonic version using `functools.reduce` with the XOR operator. Functionally identical to the explicit loop but more concise.