今天在耍leetcode第70题的时候总是提示要么超时,要么空间超了。
然后我就很不开心了,抄起数字就推,参考了知乎大神的思路,过程如下:
1.二阶递推化为一阶递推
首先,
这个二阶递推公式,似乎没办法化归啊?这是第一个难点。
我们可以假设它能变形为
这种等比数列的形式(有人问我这个假设怎么来的。呃,这要一点凑的数学直觉,就像凑不等式和凑微分。把递推式子凑出等比数列的形式,还要每项都能对应上,差不多只能设出这种形式),然后看看能不能把常数 求出来。
由上述两式得
对应常系数,有:
成功解出 A ,说明 A和 B 是可以解出来的嘛!
然后利用等比数列的性质,由(2)式得
成功地把二阶的递推式化成了一阶递推式!
2.一阶递推化为通项公式
现在故技重施,还是假设把
化为等比数列的形式,巧妙地设计待定的系数:
因为
我们挪一部分 到等号左边,假设能凑成
这种等比形式,
哇哦!这下子 的通项已经被彻底地解出来了,剩下的只是繁琐的计算。由(4)式得:
立刻得到:
其实,这个过程正是特征方程法的由来。待定系数法是如此强大!
真正的狠人没有套路,干就完了。
python代码:
class Solution:
def climbStairs(self, n: int) -> int:
# return 1/(5**0.5)*(((1+(5*0.5)/2)**n)-(((1-(5**0.5))/2)**n))
return int((((1+5**0.5) / 2)**(n+1) - ((1-5**0.5) / 2)**(n+1)) / (5**0.5))
java代码:
class Solution {
public:
int climbStairs(int n) {
double f = pow((1 + sqrt(5)) / 2, n + 1) - pow((1 - sqrt(5)) / 2, n + 1);
return int(f / sqrt(5));
}
};
参考文章: