[LeetCode] Climbing Stairs

Note: If you feel unwilling to read the long codes, just take the idea with you. The codes are unnecessarily long due to the inconvenient handle of matrices.

Well, a classic and interesting problem. The recursion is simply f(n) = f(n - 1) + f(n - 2), which means that we can either climb to n - 1 and then climb 1 step or climb to n - 2 and then climb 2 steps. So this problem is actually asking for the n-th Fibonacci number. However, if you code it in such a recursive way, it will meet TLE due to the large number of overlapping sub-problems.

There are mainly two ways to solve this problem. The first one uses the above formula in a bottom-up manner and takes O(n) time. This link shares the O(n) solution in all the supported languages of the LeetCode OJ. You may take a look at it and appreciate the appetite of each language :-)

Now I will focus on another solution, which takes O(logn) time. The idea is to use the matrix power. In fact, [f(n), f(n - 1); f(n - 1), f(n - 2)] = [1, 1; 1, 0] ^ n for n >= 2. And similar to the problem Pow(x, n), the power of a matrix can be computed in O(logn) time.

The C++ and Python codes are shown below. Note that the computation of the power of the matrix[1, 1; 1, 0] is hard-coded. Since it is a bit trickier to handle matrix multiplications, the codes become much longer.


C++

 1 class Solution {  
 2 public:
 3     int climbStairs(int n) {
 4         if (n < 2) return n;
 5         vector<int> fibs = {1, 1, 1, 0};
 6         vector<int> ans = fibPower(fibs, n);
 7         return ans[0];
 8     }
 9 private:
10     vector<int> matrixProd(vector<int>& l, vector<int>& r) {
11         vector<int> ans(4, 0);
12         ans[0] = l[0] * r[0] + l[1] * r[2];
13         ans[1] = l[0] * r[1] + l[1] * r[3];
14         ans[2] = l[2] * r[0] + l[3] * r[2];
15         ans[3] = l[2] * r[1] + l[3] * r[3]; 
16         return ans;
17     }
18     vector<int> fibPower(vector<int>& fibs, int n){
19         if (n == 1) return fibs;
20         vector<int> half1 = fibPower(fibs, n / 2);
21         vector<int> half2 = fibPower(fibs, n / 2);
22         vector<int> ans = matrixProd(half1, half2);
23         if (n % 2 == 0) return ans;
24         ans[1] = (ans[0] += ans[1]) - ans[1];
25         ans[3] = (ans[2] += ans[3]) - ans[3];
26         return ans;
27     }
28 };

 


Python

class Solution:
    # @param {integer} n
    # @return {integer}
    def climbStairs(self, n):
        if n  < 2:
            return n
        fibs = [1, 1, 1, 0]
        ans = self.fibsPower(fibs, n)
        return ans[0] 

    def matrixProd(self, l, r):
        ans = [0] * 4
        ans[0] = l[0] * r[0] + l[1] * r[2]
        ans[1] = l[0] * r[1] + l[1] * r[3]
        ans[2] = l[2] * r[0] + l[3] * r[2]
        ans[3] = l[2] * r[1] + l[3] * r[3]
        return ans

    def fibsPower(self, fibs, n):
        if n == 1:
            return fibs
        half1 = self.fibsPower(fibs, n / 2)
        half2 = self.fibsPower(fibs, n / 2)
        ans = self.matrixProd(half1, half2) 
        if n % 2 == 0:
            return ans
        ans[0], ans[1], ans[2], ans[3] = ans[0] + ans[1], ans[0], ans[2] + ans[3], ans[2]
        return ans

 

posted @ 2015-07-15 00:42  jianchao-li  阅读(253)  评论(0编辑  收藏  举报