人名算法
约瑟夫环
1823. 找出游戏的获胜者
难度中等129收藏分享切换为英文接收动态反馈
共有 n
名小伙伴一起做游戏。小伙伴们围成一圈,按 顺时针顺序 从 1
到 n
编号。确切地说,从第 i
名小伙伴顺时针移动一位会到达第 (i+1)
名小伙伴的位置,其中 1 <= i < n
,从第 n
名小伙伴顺时针移动一位会回到第 1
名小伙伴的位置。
游戏遵循如下规则:
- 从第
1
名小伙伴所在位置 开始 。 - 沿着顺时针方向数
k
名小伙伴,计数时需要 包含 起始时的那位小伙伴。逐个绕圈进行计数,一些小伙伴可能会被数过不止一次。 - 你数到的最后一名小伙伴需要离开圈子,并视作输掉游戏。
- 如果圈子中仍然有不止一名小伙伴,从刚刚输掉的小伙伴的 顺时针下一位 小伙伴 开始,回到步骤
2
继续执行。 - 否则,圈子中最后一名小伙伴赢得游戏。
给你参与游戏的小伙伴总数 n
,和一个整数 k
,返回游戏的获胜者。
示例 1:

输入:n = 5, k = 2 |
示例 2:
输入:n = 6, k = 5 |
笨比解法 模拟 效率不错
class Solution { |
数学解法
下表 0 1 2 3 4 数到3删除 |
注意 这道题因为编号是从1开始的 index 0对应的人是1 所以最后的下标要+1
class Solution { |
厄拉多塞筛

204. 计数质数
难度中等897
给定整数 n
,返回 所有小于非负整数 n
的质数的数量 。
示例 1:
输入:n = 10 |
示例 2:
输入:n = 0 |
示例 3:
输入:n = 1 |
class Solution { |
1175. 质数排列
难度简单96收藏分享切换为英文接收动态反馈
请你帮忙给从 1
到 n
的数设计排列方案,使得所有的「质数」都应该被放在「质数索引」(索引从 1 开始)上;你需要返回可能的方案总数。
让我们一起来回顾一下「质数」:质数一定是大于 1 的,并且不能用两个小于它的正整数的乘积来表示。
由于答案可能会很大,所以请你返回答案 模 mod 10^9 + 7
之后的结果即可。
示例 1:
输入:n = 5 |
示例 2:
输入:n = 100 |
class Solution { |
摩尔投票法
核心就是对拼消耗。
玩一个诸侯争霸的游戏,假设你方人口超过总人口一半以上,并且能保证每个人口出去干仗都能一对一同归于尽。最后还有人活下来的国家就是胜利。
那就大混战呗,最差所有人都联合起来对付你(对应你每次选择作为计数器的数都是众数),或者其他国家也会相互攻击(会选择其他数作为计数器的数),但是只要你们不要内斗,最后肯定你赢。
169. 多数元素
难度简单1471
给定一个大小为 n
的数组 nums
,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋
的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:nums = [3,2,3] |
示例 2:
输入:nums = [2,2,1,1,1,2,2] |
提示:
n == nums.length
1 <= n <= 5 * 104
-109 <= nums[i] <= 109
==进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。==
- 摩尔投票法
class Solution {
public:
//投票算法证明:
// 如果候选人不是maj 则 maj,会和其他非候选人一起反对 会反对候选人,所以候选人一定会下台(maj==0时发生换届选举)
// 如果候选人是maj , 则maj 会支持自己,其他候选人会反对,同样因为maj 票数超过一半,所以maj 一定会成功当选
int majorityElement(vector<int>& nums) {
int cnt = 0;
int maj = 0;
for(int i = 0; i<nums.size(); i++){
if(cnt == 0){
maj = nums[i];
cnt++;
}else{
nums[i] == maj ? cnt++ : cnt--;
}
}
return maj;
}
}; - 随机法
class Solution {
public:
// 随机数法 期望的随机次数是常数 平均时间复杂度On
// 期望计算 1*0.5 + 2*0.5*0.5 + 3*0.5*0.5...收敛于2
int majorityElement(vector<int>& nums) {
while(1){
int randNum = nums[rand() % nums.size()];
int cnt = 0;
for(int& num : nums){
if(randNum == num)
cnt++;
if(cnt>nums.size() / 2)
return randNum;
}
}
return 0;
}
}; - 位运算
class Solution {
public:
int majorityElement(vector<int>& nums) {
//位运算法,统计每个数字每一位0,1出现的次数,如果某一位1出现的次数多则该位为1,0同理;
//最后按为统计出来的数就是众数
int res=0,len = nums.size();
for(int i=0;i<32;i++){
int ones=0,zero=0;
for(int j=0;j < len; j++){
if(ones>len/2 ||zero>len/2) break;
if((nums[j]&(1<<i)) != 0) ones++;
else zero++;
}
// 还原数字
if(ones > zero)
res |= (1<<i);
}
return res;
}
};