一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第26天,点击查看活动详情。
剑指 Offer 60. n个骰子的点数
思路
(动态规划) O(n^2)
计算所有点数出现的概率,点数x出现的概率为: P(x) = x出现的次数 / 总次数
投掷 n个骰子,所有点数出现的总次数是 6^n。
掷1个骰子,点数之和范围为1 - 6。
掷2个骰子,点数之和范围为2 - 6 * 2。
因此,掷n个骰子,点数之和范围为n - 6 * n。
状态表示: f[i][j]表示投掷i个骰子,点数之和为j出现的次数。那么f[n][x]就表示投掷n个筛子,点数之和为x出现的次数。
状态计算: 我们依据最后一次投掷的点数划分集合,那么 f[i][j] += f[i - 1][j - k],k 属于 {1, 2, 3, 4, 5, 6}并且 j >= k。
初始化: 初始化 f[1][1,2,3,4,5,6] = 1 = f[0][0] 。投掷0个骰子,点数之和为0只有一种方案。
时间复杂度分析: O(n^2)
c++代码
class Solution {
public:
vector<double> dicesProbability(int n) {
vector<vector<int>> f(n + 1, vector<int>(6 * n + 1, 0));
f[0][0] = 1;
for(int i = 1; i <= n; i++){
for(int j = i; j <= 6 * i; j++)
for(int k = 1; k <= 6; k++){
if(j >= k)
f[i][j] += f[i - 1][j - k]; //6次累加起来
}
}
vector<double> res;
int total = pow(6, n);
for(int i = n; i <= 6 * n; i++){
res.push_back(f[n][i] * 1.0/ total);
}
return res;
}
};
剑指 Offer 61. 扑克牌中的顺子
思路
(数组,排序) O(n)
能组成顺子需要满足的两个条件是:
- 除了
0以外不能出现两个相同的数字。 - 排序后两个相邻数字的差值不能大于
0的个数。
具体过程如下:
-
1、将数组排序。
-
2、统计数组中
0的个数。 -
3、遍历整个数组:
- 如果在遍历过程中,出现了
0以外的两个相同的数字或者相邻数字的差值大于0的个数,则返回false。 - 维护
0的个数,用总的0的个数减去用0填补空位的数量。
- 如果在遍历过程中,出现了
-
4、如果可以遍历到数组结尾,说明当前序列合法,返回
true。
时间复杂度分析: O(n)
c++代码
class Solution {
public:
bool isStraight(vector<int>& nums) {
int cnt = 0;
sort(nums.begin(), nums.end());
for(int x : nums){
if(!x) cnt++; //统计0的个数
}
for(int i = 0; i < nums.size() - 1; i++){
if(!nums[i]) continue;
if(nums[i + 1] - nums[i] - 1> cnt) return false;
if(nums[i + 1] == nums[i]) return false;
cnt -= nums[i + 1] - nums[i] - 1;
}
return true;
}
};
剑指 Offer 62. 圆圈中最后剩下的数字
思路
(递推,动态规划) O(n)
状态表示: f[n][m]表示n个人报数,每次报m的人被杀掉,最终胜利者的下标位置。
状态计算: 每杀掉一个人,则下一个人成为第一个报数的人,相当于把数组向前移动m位。若已知n - 1个人时,胜利者的下标位置为f[n - 1][m],则n个人的时候,就是往后移动m,(因为有可能数组越界,超过的部分会被接到头上,所以还要模n),即:f[n][m] = (f[n - 1][m] + m) % n,去掉报数的一维,则f[i] = (f[i - 1] + m) % n;
下图表示11个人从1开始报数,每次报3的被杀掉。
时间复杂度分析: O(n)。
文章链接:blog.csdn.net/u011500062/…
c++代码
class Solution {
public:
int lastRemaining(int n, int m){
if (n == 1) return 0;
vector<int> f(n + 1);
f[1] = 0;
for(int i = 2; i <= n ; i ++){ //枚举人数
f[i] = (f[i - 1] + m) % i; //核心递推关系式
}
return f[n];
}
};