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:
- '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.
解题思路:
笨拙如我找不到状态转移公式。。。
这道题主要是问,给出数字n,满足要求的n个集合S中的元素的排列有多少。
集合S 有三个元素 A, L, P
要求:A 不能出现超过1次; L不能连续出现2次以上
可以对n求解降到对n-1求解,然后对满足要求的n-1个排列上尝试添加 A, L, P。
这里要求有限我们可以用枚举来枚举出有对不同的A,L满足要求的排列的个数。
A0L0: 当前排列里面不含A,且最后两个不是L, 初始为1, (可以理解为n=1, 此时只有P)
A0L1: 当前排列里面不含A,最后只有一个L,初始为1,
A0L2: 当前排列里面不含A,最后出现两个连续的L,初始为0
A1L0: 当前排列里面含有A,且最后两个不是L,初始为1
A1L1: 当前排列里面含有A,最后只有一个L, 初始为0
A1L2: 当前排列里面含有A,最后出现两个连续的L, 初始为0
若我们想要在尾部添加A,那我们只能选择A0L*
若我们想要在尾部添加L,只能选择A*L(x) x <=1
若想添加P,就随便加吧。。。
不过重点是添加后更新的这六种状态值。
时间复杂度O(n), 空间O(1)
代码:
class Solution { public: int checkRecord(int n) { unsigned int A0L0 = 1, A0L1 = 1, A0L2 = 0, A1L0 = 1, A1L1 = 0, A1L2 = 0; int mod = 1000000007; for (int i = 1; i <= n; i++) { //tmp value unsigned int pA0L0 = A0L0, pA0L1 = A0L1, pA0L2 = A0L2, pA1L0 = A1L0, pA1L1 = A1L1, pA1L2 = A1L2; //add L at the end A0L2 = pA0L1; A0L1 = pA0L0; A1L2 = pA1L1; A1L1 = pA1L0; //add p at the end A0L0 = (pA0L0 + pA0L1 + pA0L2)%mod; //add a at the end A1L0 = (pA1L0 + pA1L1 + pA1L2 + A0L0)%mod; } return A1L0; } };