刷题笔记0x08:石子游戏
创建于:发布于:文集:刷题笔记
首先,我们要求的答案是两人中谁会赢,或者说最终谁手中的石子数多。
其次,我们知道两人都是高手,将发挥出最高水平,并且石子总数为奇数,一定会有人赢。
那么让我们假设f(i, j)为对于一个序列索引i到j区间内,先手玩家最大所得与后手玩家最大所得的差值。
先假设个数组piles为[2, 7, 3, 9]的例子画个图看看。
先不急着把所有情况填满,显而易见的是,对于i == j的情况,差值显然就等于piles[i]或者说piles[j]了(因为这种情况区间里就一堆石头啊,后手根本没得拿)。
另外还可以发现,类似i == 1, j == 3和i == 3, j == 1的情况,它们表示的是同样的区间,所以我们可以抛弃表格左下角,并假定0 <= i <= size && i <= j <= size
,其中size表示题目给定的数组长度。
但是这样好像不太好总结规律,让我们稍微调整一下表格,每个表格里放两个数,分别表示先手可得的石子数和后手可得的石子数。
对于先手而言,只有两种选择,拿左边的或者右边的,我们设置一个三维数组dp[i][j][2],dp[i][j][0]表示先手在区间内可得石子数,dp[i][j][1]就是后手的了。
具体写代码时,我们要得到的答案就是表格的右上角dp[i][j][0] > dp[i][j][1]这个表达式是否为true,也就是先手是不是比后手拿的石头多。为此,我们可以试着斜着遍历数组直到右上角。
这道题的条件我隐约觉得有些不对劲,翻了一下评论,果然,这个游戏居然先手必胜,也就是说这题有个时间复杂度为O(1)的解法:
return true;