扑克牌顺子
题目描述
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
分析
既然题目中都说明了模拟,那我们就来模拟。
首先排序,计算 0 (大小王)的个数。然后对剩下的牌,计算它们的差值,看 能否用 0 填充。整体还是比较简单。代码如下:
bool IsContinuous(vector<int> numbers) {
if (numbers.size() == 0) {
return 0;
}
sort(numbers.begin(), numbers.end());
int i = 0;
int cnt = 0;
while (numbers[i] == 0) {
++cnt;
++i;
}
for (int j = i; j < numbers.size() - 1; ++j) {
if (numbers[j + 1] == numbers[j]) {
return 0;
}
if (numbers[j + 1] - numbers[j] > 1) {
cnt -= numbers[j + 1] - numbers[j] - 1;
if (cnt < 0) {
return 0;
}
}
}
return 1;
}
孩子们的游戏
题目描述
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
分析
这题也可以采用模拟,即模拟游戏进行的过程,进行筛选,知道剩下最后一个人为止。
代码如下:
int LastRemaining_Solution(int n, int m)
{
if (n == 0 || m == 0)return -1;
int *visit = new int[n];
for (int i = 0; i < n; ++i) {
visit[i] = 0;
}
//map<int, int> visit;
int cnt = 0; //计数到 n - 1 时,模拟结束
int cnt_m = 0; //计数直到 m-1
int i = 0;
while (cnt < n - 1) {
while (cnt_m < m) {
if (visit[i] == 0) {
//visit[i] = 1;
++cnt_m;
++i;
}
else {
++i;
}
if (i == n) {
i = 0;
}
}
// 这个地方容易遗忘出错
if (i == 0) {
visit[n - 1] = 1;
}
else {
visit[i - 1] = 1;
}
++cnt;
cnt_m = 0;
}
for (int i = 0; i < n; ++i) {
if (visit[i] == 0) {
return i;
}
}
return 0;
}
当然了,这个题目也有更简单的公式解法。
设 f(i, m) 为 i 个人中 删除 第 m 个 人后最后剩下的人(最终只剩下一个人),那么 f(n, m) 是 n 个人中 删除 第 m 个 人后最后剩下的人。
设 n 个人 为 0,1,2, … , n-1, 第一个删除的数字是 (m-1) % n,设 其为 k,那么第二轮的序列为
k+1, … n-1,0, …, k-1. (a)
可以将该序列做一个映射,使得映射序列为
0,1, 2,…, n-2. (b)
从 a 到 b 的映射公式为:
(x-k-1)%n.
从 b 到 a 的映射公式为:
(x+k+1)%n
设 (a)对应的表达式 f’(n-1,m), (b) 对应的表达式为 f(n-1, m)
f’(n-1, m) = f(n, m) 因为最后剩下的数是相同的。
知道了 f’(n-1,m) 和 f(n-1, m) 的关系,就知道了 f(n,m) 和 f(n-1,m) 的关系。
由 b 到 a 的映射公式可知:
f’(n-1, m) = (f(n-1, m) + k + 1) % n
将 k=(m-1)%n 代入上式,得到
f’(n-1, m) = (f(n-1, m) + m) % n
即
f(n, m) = (f(n-1, m) + m) % n
接下来就好办了。
不用加减乘除做加法
题目描述
写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。
分析
第一次碰到这种数学题目,是真的毫无办法,知道坑顶是数学上的技巧,但就是不会啊。只能慢慢积累了。。。
待续。。。
参考文献
孩子们的游戏