寻找素数
素数:只能被1或其本身整除。
实现一个函数,输入一个整数n
,返回[2, n]
中的素数个数
暴力解法:
1 | int countPrimes(int n) { |
暴力解法时间复杂度为O(n^2),不够高效。
改进:
i
只需遍历到sqrt(n)
;- 筛数法,2,3…的所有倍数都不是素数,但存在计算冗余;
- 内层
for
循环的j
从i
的平方开始遍历,不是从2 * i
开始.
1 | int countPrimes(int n) { |
模幂运算
位运算n & (n-1)
的妙用
n&(n-1)
作用:将n
的二进制表示中的最低位为1
的改为0
n = 10100
(二进制),则(n-1) = 10011
–> n&(n-1) = 10000
判断一个数是否是2的n次幂
n > 0 && ((n & (n - 1)) == 0 )
解释
((n & (n-1)) == 0):
如果
A & B == 0
,表示A与B的二进制形式没有在同一个位置都为1的时候。求某一个数的二进制表示中1的个数
while (n > 0 ) { count ++; n &= (n-1); }
幂运算
整数a
,数组b
,返回幂运算a ^ b
的结果,与1337
取模(mod,余数)运算后的结果。
例如输入a = 2, b = [1, 2]
,返回2 ^ 12
和1337
取模的结果,4096 % 1337 = 85
处理指数数组
注:b为指数数组,可以采用递归求幂,
superPow(a, [1, 2, 5, 6]) ==> superPow(a, [1, 2, 5])
处理模运算
(a * b) % base = (a % k) * (b % k) % k
对乘法的结果求模,等价于先对每个因子求模,然后对因子相乘的结果再求模。
1 | int base = 1337; |
高效求幂
幂运算的递归关系式:
a ^ b = a * a ^ (b - 1)
, b为奇数a ^ b = (a ^ (b / 2)) ^ 2
, b为偶数加上对
base
求模运算:1
2
3
4
5
6
7
8
9
10
11
12int base = 1337;
int mypow(int a, int k) {
if (k == 0) return 1;
a %= base;
if (k % 2 == 1) {
return (a * mypow(a, k - 1)) % base;
} else {
int sub = mypow(a, b / 2);
return (sub * sub) % base;
}
}
连续N个数的和
求 1 2 … n ,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。
示例:
- 输入:n = 3 输出:6
- 输入:n = 9 输出:45
限制:1 <= n <= 1000
解析:
因为不能使用公式直接计算(公式中包含乘除法),所以考虑使用递归进行求解,又不能使用if等判断返回条件,采用A && B
的特性进行判断。
如果A为true,返回B的布尔值(继续往下执行)
如果A为false,直接返回false(相当于短路)
将递归的返回条件取非然后作为 && 的第一个条件,递归主体转换为第二个条件语句。
1 | int sumNums(int n) { |
二分搜索剪枝
有 N
堆香蕉,第 i
堆中有 piles[i]
根香蕉,Koko要在H
小时内吃完,吃香蕉的速度为每小时K
根,每小时最多吃一堆香蕉,若吃不下到下一小时再吃,如果这堆香蕉少于 K
根,她将吃掉这堆的所有香蕉,然后这一小时内不会再吃更多的香蕉。 计算Koko每小时至少吃几根香蕉,才能在H
小时内全部吃完?
1 | 输入: piles = [3,6,7,11], H = 8 |
解析:求H
小时内吃完的最小速率,假设为speed
,speed
至少为1,最大为max(piles)
,一小时最多吃一堆。
暴力解法:从1开始穷举到max(piles)
,一旦发现某个值符合,就为最小速度。
改进:可以利用二分搜索剪枝,搜索左侧边界。
1 | int minSpeed(vector<int>& piles, int h) { |
传送带上的第 i
个包裹的重量为 weights[i]
。每一天,我们都会按给出重量(weights)的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。
返回能在 days
天内将传送带上的所有包裹送达的船的最低运载能力。
货物不可分割且必须按顺序运输
1 | 输入:weights = [1,2,3,4,5,6,7,8,9,10], days = 5 |
解法:本质上和koko食香蕉的问题是一样的,首先确定最小载重cap
,最小值为max(weights)
和sum(weights)
,求最小载重。
暴力法顺序遍历,改进二分搜索左侧边界剪枝。
1 | int shipWithinDays(vector<int>& weights, int days) { |