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

本文探讨两道经典算法题:爬楼梯问题与学生考勤记录问题。爬楼梯问题利用动态规划解决路径计数,而考勤记录问题则通过三维动态规划计算合法考勤组合。文章提供代码实现及优化思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值