一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
剑指 Offer 14- II. 剪绳子 II
思路
(数学) O(n) 这道题目是数学中一个很经典的问题,下面我们给出证明:
首先把一个正整数 N 拆分成若干正整数只有有限种拆法,所以存在最大乘积。 假设 N=n1+n2+…+nk,并且 n1×n2×…×nk是最大乘积。
- 显然1不会出现在其中;
- 如果对于某个 i有 ni≥5,那么把 ni 拆分成 3+(ni−3),我们有 3(ni−3)=3ni−9>ni;
- 如果 ni=4,拆成 2+2乘积不变,所以不妨假设没有4;
- 如果有三个以上的2,那么 3×3>2×2×2,所以替换成3乘积更大;
综上,选用尽量多的3,直到剩下2或者4时,用2。
时间复杂度分析:
当 n比较大时,n 会被拆分成 ⌈n/3⌉ 个数,我们需要计算这么多次减法和乘法,所以时间复杂度是O(n)。
c++代码
class Solution {
public:
int cuttingRope(int n) {
if(n <= 3) return n - 1;
long long res = 1;
if(n % 3 == 1) res = 4, n -= 4;
else if(n % 3 == 2) res = 2, n -= 2;
while(n){
res = (res * 3)% 1000000007;
n -= 3;
}
return res;
}
};
剑指 Offer 15. 二进制中1的个数
思路 (位运算)
lowbit(x) 函数的作用
lowbit(x)操作返回 x 的最后一位 1
- x=1010_2,那么 lowbit(x) 返回 10_2,即 lowbit(x)=10
- x=101000_2,那么 lowbit(x) 返回 1000_2,即 lowbit(x)=1000
lowbit 的应用:可以统计 x 中 1 的个数
就是每一次把 x 的最后一位 1 减掉,即 x−lowbit(x),只需要算下减多少次,减多少次就有多少个 1 。
c++代码
class Solution {
public:
int hammingWeight(uint32_t n) {
int res = 0;
while(n){
n -= n & -n;
res++;
}
return res;
}
};
剑指 Offer 16. 数值的整数次方
思路
(模拟,快速幂) O(logn)
快速幂模板:
LL quickPow(LL a,LL b , int mod )
{
LL res= 1;
while(b)
{
if(b&1) res = res * a %mod;
b >>= 1;
a = a*a %mod;
}
return res;
}
由于本题的指数是int范围,可能很大,所以需要用快速幂求解。
注意当指数是负数时,我们需要先取指数的绝对值,最后将乘积的倒数作为答案。
时间复杂度分析: 假设指数是 n,则一共会循环 O(logn) 次,所以时间复杂度是 O(logn)。
c++代码
class Solution {
public:
double myPow(double x, int n) {
typedef long long LL;
bool is_minus = false;
if(n < 0) is_minus = true; //判断指数是否是负数
LL k = abs(LL(n)); //取绝对值
double res = 1;
while(k){
if(k & 1) res *= x; // k是奇数
k >>= 1; //指数减半
x *= x; //底数加倍
}
if(is_minus) res = 1 / res;
return res;
}
};