题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路:
无论怎么跳,对于n级台阶,青蛙最后一跳可能是1~n。假设青蛙对于m级阶梯的跳法有f(m)种。
- 最后一跳是1,前面需要跳n-1级,所以此时为f(n-1)种可能。
- 最后一条是2, 前面需要跳n-2级,此时为f(n-2)种可能。
- …
- 最后一条是n,则青蛙一跃而上,此时只有1种跳法
故最终为f(n-1)+f(n-2)+…f(1)+1
使用动态规划,自底向上的构建思路,先计算f(1), f(2)…存储到dp数组中。
题解:
public class Solution {
public int JumpFloorII(int target) {
if(target == 0){
return 0 ;
}
if(target ==1){
return 1;
}
int[] dp = new int[target+1];
dp[0] = 0;
dp[1] = 1;
for(int i = 2; i <= target; i++){
dp[i] = 1;
for(int j = 1; j<i; j++){
dp[i] += dp[j];
}
}
return dp[target];
}
}
题目描述
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
比如n=3时,2*3的矩形块有3种覆盖方法:
题解:
这个和变态的小青蛙跳台阶差不多,甚至更简单
仍然考虑n时,最后一块的放置有两种方案:
- 竖着放一块,此时之前的长度为n-1,也就是这时应该有f(n-1)种方案。
- 横着放两块,此时之前的长度为n-2(因为瓷砖横着的长度是2),这种情况下有f(n-2)中方案。
那么对于n的解决方案数:
f
(
n
)
=
f
(
n
−
1
)
+
f
(
n
−
2
)
f(n) = f(n-1)+f(n-2)
f(n)=f(n−1)+f(n−2)
可以从底向上,也可以使用递归从上向下写。
public class Solution {
public int RectCover(int target) {
if(target==1){
return 1;
}
if(target == 0){
return 0;
}
int dp[] = new int[target+1];
dp[0] = 1;
dp[1] = 1;
for(int i=2; i<=target; i++){
dp[i] = dp[i-1]+dp[i-2];
}
return dp[target];
}
}
空间优化:
public class Solution {
public int RectCover(int target) {
if(target==1){
return 1;
}
if(target == 0){
return 0;
}
int ppre = 1;
int pre = 1;
int cur=0;
for(int i=2; i<=target; i++){
cur = pre+ppre;
ppre = pre;
pre = cur;
}
return cur;
}
}
题目描述
输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。
题解(参考牛客官方)
使用除2取模,在100000000…0,31个0时会出现问题。输出为0,我们希望输出为1.
有符号整数在计算机中以补码的形式存储的。对于正数,我们无需考虑,直接进行移位比较就好,对于负数,我们在右移的时候,左侧会自动补1。这会影响我们的判断。
所以我们的解决方案是移动mark而不是移动原数。
public class Solution {
public int NumberOf1(int n) {
int mark = 1;
int ans = 0;
while(mark!=0){
if((mark & n)!=0){
ans++;
}
mark = mark<<1;
}
return ans;
}
}