LeetCode(六) DP 70.Climbing Stairs&552. Student Attendance Record II

70.Climbing Stairs

题目要求如下

You are climbing a stair case. It takes n steps to reach to the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways
can you climb to the top?

Note: Given n will be a positive integer.

这一题类似斐波那契数列,爬到第n层要么是从n-1层一步爬上来的,要么是从n-2层两步爬上来的。可以得出递推公式f(n)=f(n-1)+f(n-2)。一开始考虑递归,但是效率太低了,可以考虑使用动态规划提高效率。
代码如下

public class Solution {
    public int climbStairs(int n) {
        if (n <= 1) return 1;
        int[] dp = new int[n];
        dp[0] = 1; dp[1] = 2;
        for (int i = 2; i < n; ++i) {
            dp[i] = dp[i - 1] + dp[i - 2];
        }
        return dp[n - 1];
    }
}

由于只需要获得最后结果,可以对空间进行优化,优化解法如下

public class Solution {
    public int climbStairs(int n) {
       // base cases
    if(n <= 0) return 0;
    if(n == 1) return 1;
    if(n == 2) return 2;

    int one_step_before = 2;
    int two_steps_before = 1;
    int all_ways = 0;

    for(int i=2; i<n; i++){
        all_ways = one_step_before + two_steps_before;
        two_steps_before = one_step_before;
        one_step_before = all_ways;
    }
    return all_ways;
    }

}

552.Student Attendance Record II

题目要求如下

Given a positive integer n, return the number of all possible
attendance records with length n, which will be regarded as
rewardable. The answer may be very large, return it after mod 10^9 + 7.

A student attendance record is a string that only contains the
following three characters:

‘A’ : Absent. ‘L’ : Late. ‘P’ : Present. A record is regarded as
rewardable if it doesn’t contain more than one ‘A’ (absent) or more
than two continuous ‘L’ (late).

Example 1:
Input: n = 2
Output: 8

Explanation: There are 8 records with length 2 will be regarded as rewardable: “PP” , “AP”, “PA”, “LP”,”PL”, “AL”, “LA”, “LL” Only “AA” won’t be regarded as rewardable owing to more than one absent times. Note: The value of n won’t exceed 100,000.

这一题同样不能使用递归的方法,考虑使用动态规划进行求解。使用三维数组记录三种不同的记录情况。

public class Solution {
   public int checkRecord(int n) {
    final int MOD = 1000000007;
    int[][][] f = new int[n + 1][2][3];

    f[0] = new int[][]{{1, 1, 1}, {1, 1, 1}};
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < 2; j++)
            for (int k = 0; k < 3; k++) {
                int val = f[i - 1][j][2]; // ...P
                if (j > 0) val = (val + f[i - 1][j - 1][2]) % MOD; // 可以有最多j个A
                if (k > 0) val = (val + f[i - 1][j][k - 1]) % MOD; // 可以有最多k个L串
                f[i][j][k] = val;
            }
    return f[n][1][2];
}
}

还有一种优化算法,没有看懂
原文链接https://discuss.leetcode.com/topic/86526/improving-the-runtime-from-o-n-to-o-log-n

动态规划是一个经典的算法,它减少了大量的计算。
一个动态规划入门教程
通过金矿模型介绍动态规划

猜你喜欢

转载自blog.csdn.net/srping123/article/details/77371576