题目837.新21点
爱丽丝参与一个大致基于纸牌游戏 “21点” 规则的游戏,描述如下:
爱丽丝以 0 分开始,并在她的得分少于 K 分时抽取数字。 抽取时,她从 [1, W] 的范围中随机获得一个整数作为分数进行累计,其中 W 是整数。 每次抽取都是独立的,其结果具有相同的概率。
当爱丽丝获得不少于 K 分时,她就停止抽取数字。 爱丽丝的分数不超过 N 的概率是多少?
用例
输入:N = 10, K = 1, W = 10
输出:1.00000
输入:N = 6, K = 1, W = 10
输出:0.60000
输入:N = 21, K = 17, W = 10
输出:0.73278
解题思路
- 思路一
- 动态规划的思路,爱丽丝获胜的概率只和下一轮开始前的得分有关,因此利用得分计算概率
- 令 dp[x] 表示从得分为 xx 的情况开始游戏并且获胜的概率,目标是求dp[0] 的值。
- 根据规则,当分数达到或超过K时游戏结束,游戏结束时,如果分数不超过 N则获胜,如果分数超过N则失败。因此当K≤x≤min(N,K+W−1)时有dp[x]=1,当x>min(N,K+W−1)时有dp[x]=0。
- 当0≤x≤K时,如何计算dp[x]的值?注意到每次在范围[1,W] 内随机抽取一个整数,且每个整数被抽取到的概率相等,因此可以得到如下状态转移方程:
- 时间复杂度O(K*W)
- 思路二
- 在上面的思路的基础上对其进行差分,考虑dp的临近项进行差分,有如下结果:
其中0<=x<K-1 - 可以得到新的状态转移方程为:
- 当x=K-1时,需要通过
- 注意到仅有K<=x<=min(N,K+W-1)时,才有dp[x] = 1,所以
- 在上面的思路的基础上对其进行差分,考虑dp的临近项进行差分,有如下结果:
- 思路三
参考这篇博客——新21点代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39class Solution:
def new21Game(self, N: int, K: int, W: int) -> float:
if K == 0:
return 1.0
dp = [0.0] * (K + W + 1)
for i in range(K,min(N,K+W+-1)+1):
dp[i] = 1
for i in range(K-1,-1,-1):
for j in range(1,W+1):
dp[i] += dp[i+j]/W
return dp[0]
class Solution2:
def new21Game(self, N: int, K: int, W: int) -> float:
if K == 0:
return 1.0
dp = [0.0] * (K + W + 1)
for i in range(K, min(N, K + W - 1) + 1):
dp[i] = 1.0
dp[K - 1] = float(min(N - K + 1, W)) / W
for i in range(K - 2, -1, -1):
dp[i] = dp[i + 1] - (dp[i + W + 1] - dp[i + 1]) / W
return dp[0]
class Solution3:
def new21Game(self, N: int, K: int, W: int) -> float:
if K == 0 or N >= K + W:
return 1.0
sums = [0.0 for i in range(K + W)]
sums[0] = 1.0
for i in range(1, K + W):
t = min(i-1, K-1)
if i <= W:
sums[i] = sums[i - 1] + sums[t] / W
else:
sums[i] = sums[i - 1] + (sums[t] - sums[i - W - 1]) / W
return (sums[N] - sums[K - 1]) / (sums[K + W - 1] - sums[K - 1])
题目528.按权重随机选择
给定一个正整数数组 w ,其中 w[i] 代表位置 i 的权重,请写一个函数 pickIndex ,它可以随机地获取位置 i,选取位置 i 的概率与 w[i] 成正比。
说明:
1 <= w.length <= 10000
1 <= w[i] <= 10^5
pickIndex 将被调用不超过 10000 次
解题思路
前缀和作为加权选择
代码
1 | class Solution: |
题目529.扫雷游戏
给定一个代表游戏板的二维字符矩阵。 ‘M’ 代表一个未挖出的地雷,’E’ 代表一个未挖出的空方块,’B’ 代表没有相邻(上,下,左,右,和所有4个对角线)地雷的已挖出的空白方块,数字(’1’ 到 ‘8’)表示有多少地雷与这块已挖出的方块相邻,’X’ 则表示一个已挖出的地雷。
现在给出在所有未挖出的方块中(’M’或者’E’)的下一个点击位置(行和列索引),根据以下规则,返回相应位置被点击后对应的面板:
如果一个地雷(’M’)被挖出,游戏就结束了- 把它改为 ‘X’。
如果一个没有相邻地雷的空方块(’E’)被挖出,修改它为(’B’),并且所有和其相邻的方块都应该被递归地揭露。
如果一个至少与一个地雷相邻的空方块(’E’)被挖出,修改它为数字(’1’到’8’),表示相邻地雷的数量。
如果在此次点击中,若无更多方块可被揭露,则返回面板。
用例
输入
1 | [['E', 'E', 'E', 'E', 'E'], |
输出
1 | [['B', '1', 'E', '1', 'B'], |
解题思路
bfs配合一个visited数组就可以,第一个方法超时严重
代码
1 | from typing import List |
发布时间: 2020-06-03
最后更新: 2020-06-03
本文标题: leetcode-day17
本文链接: http://huangketsudou.github.io/2020/06/03/leetcode-day17/
版权声明: 本作品采用 CC BY-NC-SA 4.0 许可协议进行许可。转载请注明出处