「力扣」第 877 题:石子游戏(动态规划)

地址:https://leetcode-cn.com/problems/stone-game/

方法一:记忆化递归

Java 代码:

import java.util.Arrays;

public class Solution {

    public boolean stoneGame(int[] piles) {
        int len = piles.length;
        int[][] memo = new int[len][len];

        for (int i = 0; i < len; i++) {
            Arrays.fill(memo[i], -99999999);
            memo[i][i] = piles[i];
        }
        return stoneGame(piles, 0, len - 1, memo) > 0;
    }


    /**
     * 计算子区间 [left, right] 里先手能够得到的分数
     *
     * @param piles
     * @param left
     * @param right
     * @return
     */
    private int stoneGame(int[] piles, int left, int right, int[][] memo) {
        if (memo[left][right] != -99999999) {
            return memo[left][right];
        }

        if (left == right) {
            return piles[left];
        }

        int res = Math.max(piles[left] - stoneGame(piles, left + 1, right, memo),
                piles[right] - stoneGame(piles, left, right - 1, memo));
        memo[left][right] = res;
        return res;
    }


}

方法二:动态规划

Java 代码:

public class Solution {

    public boolean stoneGame(int[] piles) {
        int len = piles.length;
        int[][] dp = new int[len][len];

        for (int i = 0; i < len; i++) {
            dp[i][i] = piles[i];
        }

        // 注意顺序,新值一定要参考旧址
        for (int k = 2; k <= len; k++) {
            // i 表示左边界
            for (int i = 0; i < len - k + 1; i++) {
                // j 表示右边界
                int j = i + k - 1;
                dp[i][j] = Math.max(piles[i] - dp[i + 1][j], piles[j] - dp[i][j - 1]);
            }
        }
        return dp[0][len - 1] > 0;
    }
}

方法三:动态规划(状态压缩)

Java 代码:

public class Solution {

    public boolean stoneGame(int[] piles) {
        int len = piles.length;
        int[] dp = new int[len];

        for (int i = 0; i < len; i++) {
            dp[i] = piles[i];
        }

        // 注意顺序,新值一定要参考旧址
        for (int k = 2; k <= len; k++) {
            // i 表示左边界
            for (int i = 0; i < len - k + 1; i++) {
                // j 表示右边界
                int j = i + k - 1;
                dp[i] = Math.max(piles[i] - dp[i + 1], piles[j] - dp[i]);
            }
        }
        return dp[0] > 0;
    }
}

方法四:数学解

Java 代码:

public class Solution {

    // Alex 总是赢得 2 堆时的游戏
    // 通过一些努力,我们可以获知他总是赢得 4 堆时的游戏

    // 反推
    // 如果 Alex 最初获得第一堆,她总是可以拿第三堆
    // 如果他最初取到第四堆,她总是可以取第二堆。

    // [重点]
    // 比较:第一 + 第三,第二 + 第四 中的至少一组是更大的,所以她总能获胜

    public boolean stoneGame(int[] piles) {
        return true;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值