[Leetcode] 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 109 + 7.

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

  1. 'A' : Absent.
  2. 'L' : Late.
  3. '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.

思路

1、DP:将符合条件的字符串分为六种类型,并分别定义数组如下:

1)dp(里面不含有A,并且结尾不是“L”):只能以P结尾,所以dp[i] = dp[i-1] + dpl[i-1] + dpll[i-1]。

2)dpl(里面不含有A,并且结尾是“L”):只能在dp的基础上加上L结尾,所以dpl[i] = dp[i-1]。

3)dpll(里面不含有A,并且结尾是“LL”):只能在dpl的基础上加上L结尾,所以dpll[i] = dpl[i-1]。

4)dpa(里面含有A,并且结尾不是“L”):如果以P结尾,则dpa[i] = dpa[i-1] + dpal[i-1] + dpall[i-1];如果以A结尾,则dpa[i] = dp[i-1] + dpl[i-1] + dpll[i-1]。

5)dpal(里面含有A,并且结尾是“L”):只能在dpa的基础上加上L结尾,所以dpal[i] = dpa[i-1]。

6)dpall(里面含有A,并且结尾是“LL”):只能在dpal的基础上加上L结尾,所以dpall[i] = dpal[i-1]。

最后返回的应该是ret = dp[n] + dpl[n] + dpll[n] + dpa[n] + dpal[n] + dpall[n]。但是由于返回的结果可能会非常大,所以我们用long long来表示,并且每递推完成之后都取模,以防止溢出。这样算法的时间复杂度就为O(n),空间复杂度也是O(n)。

2、DFS:这道题目当然也可以用DFS + BackTracking来实现,但是时间复杂度特别高,只能通过20个测试用例。这里也把代码贴出来供读者进行比较。

代码

1、DP:

class Solution {
public:
    int checkRecord(int n) {
        long long mod = 1000000007;
        vector<long long> dp(n + 1, 0);               // contains no 'A', with no ending 'L'
        vector<long long> dpl(n + 1, 0);              // contains no 'A', with ending "L"
        vector<long long> dpll(n + 1, 0);             // contains no 'A', with ending "LL"
        vector<long long> dpa(n + 1, 0);              // contains 'A', with no ending "L"
        vector<long long> dpal(n + 1, 0);             // contains 'A', with ending "L"
        vector<long long> dpall(n + 1, 0);            // contains 'A', with ending "LL"
        dp[1] = 1;                              // "P"
        dpl[1] = 1;                             // "L"
        dpa[1] = 1;                             // "A"
        for (int i = 2; i <= n; ++i) {
            dp[i] = dp[i - 1] + dpl[i - 1] + dpll[i - 1];       // can only ends with 'P'
            dpl[i] = dp[i - 1];                                 // can only ends with 'L'
            dpll[i] = dpl[i - 1];                               // can only ends with 'L'
            dpa[i] = dpa[i - 1] + dpal[i - 1] + dpall[i - 1] +  // ends with "P" or
                     dp[i - 1] + dpl[i - 1] + dpll[i - 1];      // ends with "A"
            dpal[i] = dpa[i - 1];                               // can only ends with 'L'
            dpall[i] = dpal[i - 1];                             // can only ends with 'L'
            dp[i] %= mod, dpl[i] %= mod, dpll[i] %= mod;
            dpa[i] %= mod, dpal[i] %= mod, dpall[i] %= mod;
        }
        return (dp[n] + dpl[n] + dpll[n] + dpa[n] + dpal[n] + dpall[n]) % mod;
    }
};

2、DFS:

class Solution {
public:
    int checkRecord(int n) {
        int ret = 0, number_L = 0;
        bool contain_A = false;
        DFS(n, 0, ret, contain_A, number_L);
        return ret;
    }
private:
    void DFS(int n, int index, int &ret, bool &contain_A, int &number_L) {
        if (index == n) {
            ++ret;
            return;
        }
        int num_L = 0;
        // try to put 'P' at index
        DFS(n, index + 1, ret, contain_A, num_L);
        // try to put 'A' at index
        if (!contain_A) {
            contain_A = true;
            num_L = 0;
            DFS(n, index + 1, ret, contain_A, num_L);
            contain_A = false;
        }
        // try to put 'L'
        if (number_L <= 1) {
            num_L = number_L + 1;
            DFS(n, index + 1, ret, contain_A, num_L);
        }
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值