方法一:数学法
先手可以控制自己拿所有下标为奇数的石堆或者拿所有下标为偶数的石堆,只要先计算一下奇数石堆的石子总数和偶数石堆的石子总数哪种多就选哪种,所以先手总会赢
return true;
方法二:动态规划
假设先手和后手都最聪明的情况下,返回先手和后手拿到的石头个数之差
dp数组定义:
dp[i][j][0]
从下标i到j
堆石头,先手能获得的最大数量;dp[i][j][1]
表示后手
public boolean stoneGame(int[] piles) {
int n = piles.length;
int[][][] dp = new int[n][n][2];//dp数组定义:dp[i][j][0]从下标i到j堆石头,先手能获得的最大数量;dp[i][j][1]表示后手
for(int i=0;i<n;i++){ //base case:当i=j时,先手拿完了,后手没得拿
dp[i][i][0] = piles[i];
dp[i][i][1] = 0;
}
for(int i=n-2;i>=0;i--){//从下到上,从左到右遍历
for(int j=i+1;j<n;j++){
int left = piles[i]+dp[i+1][j][1];
int right = piles[j]+dp[i][j-1][1];
if(left>right){
dp[i][j][0] = left;
dp[i][j][1] = dp[i+1][j][0];
}
else{
dp[i][j][0] = right;
dp[i][j][1] = dp[i][j-1][0];
}
}
}
return dp[0][n-1][0]>dp[0][n-1][1];