一、剑指offer 14- I. 剪绳子
题目链接:力扣
题目描述:给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
解题思路:这道题是经典的数学问题,假设 N=n1+n2+…+nk,并且 n1×n2×…×nk 是最大乘积。
- 显然1不会出现在其中;
- 如果对于某个 i 有 ni≥5,那么把 nini 拆分成 3+(ni−3),我们有 3(ni−3)=3ni−9>ni;
- 如果 ni=4,拆成 2+2乘积不变,所以不妨假设没有4;
- 如果有三个以上的2,那么 3×3>2×2×23,所以替换成3乘积更大;
综上,选用尽量多的3,直到剩下2或者4时,用2。
时间复杂度分析:当 n 比较大时,n 会被拆分成 ⌈n/3⌉ 个数,我们需要计算这么多次减法和乘法,所以时间复杂度是 O(n)。
解题代码:
class Solution {
public:
int cuttingRope(int n) {
if(n<=3) return 1*(n-1);
int res = 1;
if(n%3==1) res=4,n-=4;
if(n%3==2) res=2,n-=2;
while(n){
res*=3;
n-=3;
}
return res;
}
};
二、剑指offer 14- II. 剪绳子 II
题目链接:给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m - 1] 。请问 k[0]*k[1]*...*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
解题思路:这道题和上一题一样的思路,只是把数据加强了,把res设为long long就好了。
解题代码:
class Solution {
public:
int cuttingRope(int n) {
if(n<=3) return 1*(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*=3;
res%=1000000007;
n-=3;
}
return res%1000000007;
}
};
三、剑指 Offer 15. 二进制中1的个数
题目链接:力扣
题目描述:编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为 汉明重量).)。
示例 1:
输入:n = 11 (控制台输入 00000000000000000000000000001011)
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。
解题思路:这题是很明显的位运算,n&1判断最后一位为1还是0,这个操作也可以用在判断奇偶上,n>>=1,把n向右移动一位。线性扫描过去,直到这个数为0。时间复杂度:O(n)
解题代码:
class Solution {
public:
int hammingWeight(uint32_t n) {
int res = 0;
while(n){
res+=n&1;
n>>=1;
}
return res;
}
};
四、剑指 Offer 16. 数值的整数次方
题目链接:力扣
题目描述:实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。
示例 1:
输入:x = 2.00000, n = 10
输出:1024.00000
解题思路:这道题我们要看n是正数还是负数,正数的话结果是大于1的正数,负数的话结果是小于1 的负数。
解题代码:
class Solution {
public:
double myPow(double x, int n) {
double res=1.0;
for(int i=n;i!=0;i/=2){
if(i&1) res*=x;
x*=x;
}
return n<0?1/res:res;
}
};