面试题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
示例 2:
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
提示:
2 <= n <= 58
贪心:根据分析,需要尽可能多的剪出长度为3的绳子,且尽量不剪出长为1的绳子,若有剩下长为1的,与前一个3重新组合4,再切为两段长为2的【此时2*2刚好等于4】
class Solution {
public:
int cuttingRope(int n) {
if(n<2)
return 0;
if(n==2)
return 1;
if(n==3)
return 2;
int a=1;
while(n>4)
{
n-=3;
a*=3;
}
return a*n;
}
};
或
int cuttingRope(int n) {
if(n <= 3) return n - 1; //必须切一刀
//n >= 5 2*(n-2) > n 3*(n-3) > n 且3*(n-3) >= 2*(n-2)
//n = 4 2 * 2 > 1 * 3
//2和3不能再分了 分了就变小了 且3优于2
int a = n / 3;
int b = n % 3;
if(b == 0){
//全部分成3
return pow(3, a);
}
if(b == 1){
//n = 10 3 * 3 * 3 * 1 ==> 3 * 3 * 2 * 2
//4 1 和 3 要变成2 * 2
return pow(3, a-1) * 4;
}
//b == 2 2不能再分了
return pow(3, a) * 2;
}
动态规划:
dp[i]表示i的最大子段乘积
dp[i]表示在i之前的状态的乘积
从dp[j]转移到dp[i]又有两个选择:j分割,j不分割。其中dp[j]存放分割情况下的最大值,而j刚好为不分割的值。
class Solution {
public:
int cuttingRope(int n) {
int *dp=new int[n+1];
dp[1]=1;
for(int i=2;i<=n;i++)
{
for(int j=1;j<i;j++)
{
dp[i]=max(dp[i],max(j*(i-j),dp[j]*(i-j)));
}
}
return dp[n];
delete[] dp;
}
};
面试题14- II. 剪绳子 II
给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]…k[m] 。请问 k[0]k[1]…*k[m] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:
输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36
提示:
2 <= n <= 1000
解法同上,只是要取模
class Solution {
public:
int cuttingRope(int n) {
if(n<2)
return 0;
if(n==2)
return 1;
if(n==3)
return 2;
long long a=1;
long long q=1000000007;
while(n>4)
{
n-=3;
a*=3;
a%=q;
}
return a*n%1000000007;
}
};
面试题15. 二进制中1的个数
请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 9 表示成二进制是 1001,有 2 位是 1。因此,如果输入 9,则该函数输出 2。
示例 1:输入:00000000000000000000000000001011
输出:3
解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 ‘1’。
示例 2:
输入:00000000000000000000000010000000
输出:1
解释:输入的二进制串 00000000000000000000000010000000 中,共有一位为 ‘1’。
示例 3:
输入:11111111111111111111111111111101
输出:31
解释:输入的二进制串 11111111111111111111111111111101 中,共有 31 位为 ‘1’
思想:每次去掉二进制中最右边的1,直到整个二进制全为0
class Solution {
public:
int hammingWeight(uint32_t n) {
int count=0;
while(n!=0)
{
count++;
n&=(n-1);
}
return count;
}
};
或者只看最右边的是否为1,然后右移:
class Solution {
public:
int hammingWeight(uint32_t n) {
int count=0;
while(n!=0)
{
if(n&1)
count++;
n=n>>1;
}
return count;
}
};