默认格式:
class Solution {
public int climbStairs(int n) {
}
}
解题思路:
1,找通式
这个应该能够找到通式才对。
1:1种
2:2种
3:3种
4:5种
5:8种
6:13种
7:21种
。。。找不到通式
2,递归
这么简单一道题要用递归真的很蠢诶。
递归的思想,给一个当前数,和一个终点数,然后进行两次递归,第一次是+1,第二次是+2.当当前值是结果值时,方法数+1,超过结果值时不加1.
在做的时候自己优化了一下,把+1变成了减1,把0作为了终点
int times=0;
public int climbStairs(int n) {
if(n-1==0){
times++;
}
else if(n-1>0)
climbStairs(n-1);
if (n-2==0)
times++;
else if(n-1>0)
climbStairs(n-2);
return times;
}
3,找规律
虽然不能使用通式,但是在之前的那个找通式的过程中我发现了一个规律。虽然直接找种类数有点困难,但是我们可以对其进行分段。将其分为a个1和b个2的组合种类有多少种,比如5有3中类型,五个1,3个1一个2,两个2一个1,我们可以再通过公式计算,三个1和1个2能产生几种可能。
1个1和n个2 能产生n中可能
1个2和m个1 能产生m中可能
2个1和n个2 能产生 ((n-1)+1)*(n-1)/2
到这里其实就已经足够了,我们可以发现当我们求2个1和n个2 的组合时,可以将其分为1个1个n个2的组合,以及n-1个2和2个1的组合,而因为2 个1和n个2的组合我们实际上还是有公式可以计算的,所以我们只针对超过3的数进行分解。
将3个1和3个2分解成计算2个1和3个2的个数加上2个2和3个1的个数的和
核心思想,使用递归将n个1和m个b逐步分解成求2个1和m个b和2个b和n个1的总数和。
代码实现如下:
public int stair(int num1,int num2){
if (num1==2){
return (num2+1)*(num2+2)/2;
}
else if (num2==2)
{
return (num1+1)*(num1+2)/2;
}
else
return stair(num1-1,num2 )+stair(num1,num2-1);
}
现在要考虑的是如何将一个正整数n分解成a个1和b个2
居然超过了100%比我想象得要好。
public int climbStairs(int n) {
int times=0;
for (int num1=n,num2=0;num2<=n/2;){
if (num1==0||num2==0)
times++;
else if (num1==1)
times+=num1*(num2+1);
else if (num2==1)
times+=num2*(num1+1);
else
times+=stair(num1,num2 );
num1-=2;
num2++;
}
return times;
}
public int stair(int num1,int num2){
if (num1==2){
return (num2+1)*(num2+2)/2;
}
else if (num2==2)
{
return (num1+1)*(num1+2)/2;
}
else
return stair(num1-1,num2 )+stair(num1,num2-1);
}
看一下答案有什么巧妙的解法把。
public int climbStairs(int n) {
double sqrt5 = Math.sqrt(5);
double fibn = Math.pow((1 + sqrt5) / 2, n + 1) - Math.pow((1 - sqrt5) / 2, n + 1);
return (int)(fibn / sqrt5);
}
答案居然有通项公式,而且只需要0ms,我凭什么拿100%[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
今天的题目告诉我一个道理,有些人天生就是比别人笨的,这是后天再怎么努力也无法弥补的事实。
上面列出来的公式这么简单我居然都没找到规律。
1:1种
2:2种
3:3种
4:5种
5:8种
6:13种
7:21种
1+2=3
2+3=5
3+5=8
每一级都是前面两级的和,而且就算规律没有找到,我也没能理解题目的思路,走台阶已经把题目形容地那么形象了,我却还把他理解成求所有组合可能的题目。
如果要走上第n级台阶,那么上一步必定是第n-2或者n-1级台阶,那么他在走着n-2和n-1级台阶的所有组合可能之和就是第n级台阶的组合数。这么简单的道理我做完了题目都没能明白。
如果理解了这一题要表达的内容,应该只需要3分钟就能把代码写出来
public int climbStairs(int n) {
int p=1;
int q=2;
for (int i=2;i<n-1;i++){
if (p>q)
q=p+q;
else
p=p+q;
}
if (n==1)
return 1;
if (n==2)
return 2;
return p+q;
}