acwing-16
骰子的点数(简单)
将一个骰子投掷n次,获得的总点数为s,s的可能范围为n~6n。
掷出某一点数,可能有多种掷法,例如投掷2次,掷出3点,共有[1,2],[2,1]两种掷法。
请求出投掷n次,掷出n~6n点分别有多少种掷法。
样例1
输入:n=1
输出:[1, 1, 1, 1, 1, 1]
解释:投掷1次,可能出现的点数为1-6,共计6种。每种点数都只有1种掷法。所以输出[1, 1, 1, 1, 1, 1]。
样例2
输入:n=2
输出:[1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
解释:投掷2次,可能出现的点数为2-12,共计11种。每种点数可能掷法数目分别为1,2,3,4,5,6,5,4,3,2,1。
所以输出[1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]。
- 采用动态规划思路
- 设置二维数组
dp[i][j]
表示i个骰子投掷出点数为j的投掷方法 - 递推式
dp[i][j]=dp[i-1][j-1]+dp[i-1][j-2]+dp[i-1][j-3]+dp[i-1][j-4]dp[i-1][j-5]+dp[i-1][j-6]
- 结果为
dp[n][n]--dp[n][6n]
class Solution {
public:
vector<int> numberOfDice(int n) {
//dp[i][j]表示i个骰子投掷出点数为j的投掷方法
vector<vector<int>> dp(n+1,vector<int>(6*n+1));
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=6*i;j++){
for(int k=1;k<=min(j,6);k++)
dp[i][j]+=dp[i-1][j-k];
}
}
vector<int> res;
for(int i=n;i<=6*n;i++)res.push_back(dp[n][i]);
return res;
}
};
扑克牌的顺子(简单)
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。
2~10为数字本身,A为1,J为11,Q为12,K为13,大小王可以看做任意数字。
为了方便,大小王均以0来表示,并且假设这副牌中大小王均有两张。
样例1
输入:[8,9,10,11,12]
输出:true
样例2
输入:[0,8,9,11,12]
输出:true
- 特判数组是否为空
- 先将数组中零跳出计算
- 判断是否有对子
- 数组中除零之外最大值最小值的差是否为小于4(因为只有五张牌)
class Solution {
public:
bool isContinuous( vector<int> numbers ) {
if(numbers.size()==0)return false;
sort(numbers.begin(),numbers.end());
int k=0;
while(numbers[k]==0)k++;
for(int i=k+1;i<numbers.size();i++)
if(numbers[i-1]==numbers[i])return false;
return numbers.back()-numbers[k]<=4;
}
};
圆圈中最后剩下的数字(简单)
0, 1, …, n-1这n个数字(n>0)排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。
求出这个圆圈里剩下的最后一个数字。
样例
输入:n=5 , m=3
输出:3
- 数组模拟
- 将数组的元素值记为下一个元素值的下标
- 每次将游标游动m-1位,将元素的下标值修改为-1
- 这样到最后,所有元素值要么是-1要么是元素下标本身,而元素下标本身即为答案
class Solution {
public:
int lastRemaining(int n, int m){
vector<int> ans;
for(int i=0;i<n;i++)
ans.push_back((i+1)%n);
int pos,f=0;
while(ans[f]!=f){
for(int i=0;i<m-1;i++){pos=f;f=ans[f];}
ans[pos]=ans[f];ans[f]=-1;f=ans[pos];
}
return ans[f];
}
};
-
约瑟夫递推
-
设置递推表达式
f(n,m)
表示n个人围成圈,从这个圆圈中删除第m个数字所得到的人的编号 -
递推关系
-
假设我们在这个圆圈中删除第m-1号人(n从零号开始)
-
那么我们将从第m号人开始从新从0开始编号
-
那么我们可以得到原始编号和新的编号的映射关系应该是
旧编号=(新编号+m)%n
-
而删除一个人之后表达式就变成了
f(n-1.m)
-
从而可以得到递推关系是
f(n,m)=(f(n-1,m)+m)%n
-
class Solution {
public:
int lastRemaining(int n, int m){
if(n==1)return 0;
return (lastRemaining(n-1,m)+m)%n;
}
};