[LintCode] Coins in a Line II
Posted Push your limit!
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[LintCode] 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?
Example
Given values array A = [1,2,2]
, return true
.
Given A = [1,2,4]
, return false
.
Solution 1. Recursion
In order for the first player to win, the coin value he gets must be bigger than a half of the total value of n coins.
For a given start index that the first player can pick one or two coins at, he can either pick one coin of values[startIdx] or two coins of values[startIdx] + values[startIdx + 1].
Given that the second player plays optimally too, we have the following optimal substructure.
As we can see from the optimal substructure, there exists many overlapping subproblems that are redundantly recomputed, making this recursive solution inefficient.
26 int pickOneVal = Math.min(fPMaxValue(values, startIdx + 2, currVal),
27 fPMaxValue(values, startIdx + 3, currVal)) + values[startIdx];
28 int pickTwoVal = Math.min(fPMaxValue(values, startIdx + 3, currVal),
29 fPMaxValue(values, startIdx + 4, currVal)) + values[startIdx] + values[startIdx + 1];
30 return Math.max(pickOneVal, pickTwoVal);
1 public class Solution { 2 public boolean firstWillWin(int[] values) { 3 if(values == null || values.length == 0){ 4 return false; 5 } 6 if(values.length <= 2){ 7 return true; 8 } 9 int sum = 0; 10 for(int i = 0; i < values.length; i++){ 11 sum += values[i]; 12 } 13 return fPMaxValue(values, 0, 0) > sum / 2; 14 } 15 private int fPMaxValue(int[] values, int startIdx, int currVal){ 16 int diff = values.length - startIdx; 17 if(diff == 2 || diff == 3){ 18 return currVal + values[startIdx] + values[startIdx + 1]; 19 } 20 if(diff == 1){ 21 return currVal + values[startIdx]; 22 } 23 if(diff <= 0){ 24 return currVal; 25 } 26 int pickOneVal = Math.min(fPMaxValue(values, startIdx + 2, currVal), 27 fPMaxValue(values, startIdx + 3, currVal)) + values[startIdx]; 28 int pickTwoVal = Math.min(fPMaxValue(values, startIdx + 3, currVal), 29 fPMaxValue(values, startIdx + 4, currVal)) + values[startIdx] + values[startIdx + 1]; 30 return Math.max(pickOneVal, pickTwoVal); 31 } 32 }
Solution 2. Dynamic Programming
Since solution 1 has both optimal substructure and overlapping subproblems, we can apply dynamic programming to avoid redundant recomputation of subproblems.
Dp state: dp[i] is the most value player one can get when there is i coins left.
Dp function:
dp[i] = Math.max(Math.min(dp[i - 2], dp[i - 3]) + values[n - i], Math.min(dp[i - 3], dp[i - 4]) + values[n - i] + values[n - i + 1]);
1 public class Solution { 2 public boolean firstWillWin(int[] values) { 3 if(values == null || values.length == 0){ 4 return false; 5 } 6 if(values.length <= 2){ 7 return true; 8 } 9 int sum = 0; 10 for(int i = 0; i < values.length; i++){ 11 sum += values[i]; 12 } 13 int n = values.length; 14 int[] dp = new int[n + 1]; 15 dp[0] = 0; 16 dp[1] = values[n - 1]; 17 dp[2] = values[n - 2] + values[n - 1]; 18 dp[3] = values[n - 3] + values[n - 2]; 19 for(int i = 4; i <= n; i++){ 20 dp[i] = Math.max(Math.min(dp[i - 2], dp[i - 3]) + values[n - i], 21 Math.min(dp[i - 3], dp[i - 4]) + values[n - i] + values[n - i + 1]); 22 } 23 return dp[n] > sum / 2; 24 } 25 }
以上是关于[LintCode] Coins in a Line II的主要内容,如果未能解决你的问题,请参考以下文章
[LintCode] Coins in a Line 一条线上的硬币
[LintCode] 395. Coins in a Line 2_Medium tag: Dynamic Programming, 博弈
[LintCode] 394. Coins in a Line_ Medium tag:Dynamic Programming_博弈
[LeetCode] 877. Stone Game == [LintCode] 396. Coins in a Line 3_hard tag: 区间Dynamic Programming, 博弈(