Thursday, April 4, 2019

Lintcode 395. Coins in a Line II

There are n coins with different value in a line. Two players take turns to take one or two coins from left side until there are no more coins left. The player who take the coins with the most value wins.
Could you please decide the first player will win or lose?
If the first player wins, return true, otherwise return false.

Example

Example 1:
Input: [1, 2, 2]
Output: true
Explanation: The first player takes 2 coins.
Example 2:
Input: [1, 2, 4]
Output: false
Explanation: Whether the first player takes 1 coin or 2, the second player will gain more value.

Solution 1 DP:
We define dp[n + 1], where dp[i]  means from A[i] to the end, the max score diff between the two players.

dp[n]= A[i - 1];
dp[n - 1] = A[i - 1] + A[i - 2];

dp[i] = max(A[i - 1] - dp[i + 1], A[i - 1] + A[i] - dp[i + 2]);

return dp[1]

Code (Java):
public class Solution {
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    public boolean firstWillWin(int[] values) {
        if (values == null || values.length <= 2) {
            return true;
        }
        
        int n = values.length;
        
        int[] dp = new int[n + 1];
        dp[n] = values[n - 1];
        dp[n - 1] = values[n - 2] + values[n - 1];

        for (int i = n - 2; i >= 1; i--) {
            dp[i] = Math.max(values[i - 1] - dp[i + 1], values[i] + values[i - 1] - dp[i + 2]);
        }
        
        return dp[1] > 0;
    }
}
Solution 2: DFS with Memorization
public class Solution {
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    public boolean firstWillWin(int[] values) {
        if (values == null || values.length <= 2) {
            return true;
        }
        
        int n = values.length;
        
        int[] dp = new int[n];
        dp[n - 1] = values[n - 1];
        dp[n - 2] = values[n - 2];
        
        return firstWillWinHelper(values, 0, dp) > 0;
    }
    
    private int firstWillWinHelper(int[] values, int i, int[] dp) {
        if (i >= values.length) {
            return 0;
        }

        if (dp[i] != 0) {
            return dp[i];
        }
        
        dp[i] = values[i] - firstWillWinHelper(values, i + 1, dp);
        if (i != values.length - 1) {
            dp[i] = Math.max(dp[i], values[i] + values[i + 1] - firstWillWinHelper(values, i + 2, dp));
        }
        
        return dp[i];
    }
}

No comments:

Post a Comment