You are given an array of integers coins
where coins[i]
is the value of the i-th
coin. There are two players playing a game optimally, alternate turns, where the first player starts picking either the first coin or the last coin from the row. The player who collects the coins with the maximum total value is the winner.
Return the winning player. If the total coins collected by the first player is more than the second player, return 1. Otherwise, if the total coins collected by second player is more than the first player, return 2. If both players collect the same amount, return 0.
This is a typical game theory problem that can be efficiently solved using dynamic programming. The goal is to calculate two values:
We will use a bottom-up dynamic programming approach to solve this:
dp[left][right]
as the maximum value the current player can collect from coins[left:right+1]
.left
and right
define a subarray from left
to right
in coins
.left == right
, the player can only pick one coin, i.e., coins[left]
.Recurrence relation:
coins[left]
, the next player’s optimal choice will be dp[left+1][right]
, and the current maximum is coins[left] + sum(coins[left+1:right+1]) - dp[left+1][right]
.coins[right]
, the next player’s optimal choice will be dp[left][right-1]
, and the current maximum is coins[right] + sum(coins[left:right]) - dp[left][right-1]
.Let’s implement this in Python:
def find_winning_player(coins):
n = len(coins)
if n == 0:
return 0
# Initializing dp array and sum array
dp = [[0]*n for _ in range(n)]
sum_coins = [0]*(n+1)
# Compute the prefix sum
for i in range(n):
sum_coins[i+1] = sum_coins[i] + coins[i]
# Base cases
for i in range(n):
dp[i][i] = coins[i]
# Dynamic programming to fill dp table
for length in range(2, n+1):
for left in range(n - length + 1):
right = left + length - 1
dp[left][right] = max(
coins[left] + (sum_coins[right+1] - sum_coins[left+1]) - dp[left+1][right],
coins[right] + (sum_coins[right] - sum_coins[left]) - dp[left][right-1]
)
# Final computation of sums
total_sum = sum(coins)
first_player = dp[0][n-1]
second_player = total_sum - first_player
if first_player > second_player:
return 1
elif second_player > first_player:
return 2
else:
return 0
# Example
coins = [1, 5, 2]
print(find_winning_player(coins)) # Output should be 1 or 2 depending on who can optimize better.
The time complexity of this approach is O(n^2)
, where n
is the length of the coins
array. This is because we are building up solutions for all subarrays of coins
, and each subarray computation involves a constant amount of work.
Got blindsided by a question you didn’t expect?
Spend too much time studying?
Or simply don’t have the time to go over all 3000 questions?