JavaInterview JavaInterview
首页
指南
分类
标签
归档
  • CSDN (opens new window)
  • 文档集合 (opens new window)
  • 系统架构 (opens new window)
  • 微信号 (opens new window)
  • 公众号 (opens new window)

『Java面试+Java学习』
首页
指南
分类
标签
归档
  • CSDN (opens new window)
  • 文档集合 (opens new window)
  • 系统架构 (opens new window)
  • 微信号 (opens new window)
  • 公众号 (opens new window)
  • 指南
  • 简历

  • Java

  • 面试

  • 算法

  • algorithm
  • leetcode
JavaInterview.cn
2022-09-13
目录

学生出勤记录 IIJava

文章发布较早,内容可能过时,阅读注意甄别。

# 题目

可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:

  • 'A':Absent,缺勤
  • 'L':Late,迟到
  • 'P':Present,到场

如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:

  • 按 总出勤 计,学生缺勤('A')严格 少于两天。
  • 学生 不会 存在 连续 3 天或 连续 3 天以上的迟到('L')记录。

给你一个整数 n ,表示出勤记录的长度(次数)。请你返回记录长度为 n 时,可能获得出勤奖励的记录情况 数量 。答案可能很大,所以返回对 109 + 7 取余 的结果。

示例 1:

输入:n = 2
输出:8
解释:
有 8 种长度为 2 的记录将被视为可奖励:
"PP" , "AP", "PA", "LP", "PL", "AL", "LA", "LL" 
只有"AA"不会被视为可奖励,因为缺勤次数为 2 次(需要少于 2 次)。

示例 2:

输入:n = 1
输出:3

示例 3:

输入:n = 10101
输出:183236316

提示:

  • 1 <= n <= 105

# 思路

//     分两种情况:
// 1.没有A:即长度为n的字符串,P、L两个字母满足规则的排列数量;
// 2.有一个A:即A将长度为n的字符串分隔为2段,A前面的长度为i,A后面的长度为n-1-i,这两段的情况与情况1相同,只是长度不同,这种情况的排列数量是两段排列数量的乘积,当然,i要从0遍历到n。

// 定义dp数组dp[i][j],表示第i天,字符串结尾L字符连续的个数为j时,可以获得出勤奖励的记录情况的数量,j取值0,1,2是有意义的,边界条件dp[0][0] = 1。
// dp[i][0]可以由dp[i-1][0]、dp[i-1][1]、dp[i-1][2]转移而来,因为只要今天是P就可以;
// dp[i][1]一定由dp[i-1][0]转移而来,因为今天是L的情况下,昨天只能是P;
// dp[i][2]一定由dp[i-1][1]转移而来,因为两天都是L的情况下,昨天只能是L;

// p.s. 实在不会取模,就用long糊弄了

# 解法


class Solution {
//     分两种情况:
// 1.没有A:即长度为n的字符串,P、L两个字母满足规则的排列数量;
// 2.有一个A:即A将长度为n的字符串分隔为2段,A前面的长度为i,A后面的长度为n-1-i,这两段的情况与情况1相同,只是长度不同,这种情况的排列数量是两段排列数量的乘积,当然,i要从0遍历到n。

// 定义dp数组dp[i][j],表示第i天,字符串结尾L字符连续的个数为j时,可以获得出勤奖励的记录情况的数量,j取值0,1,2是有意义的,边界条件dp[0][0] = 1。
// dp[i][0]可以由dp[i-1][0]、dp[i-1][1]、dp[i-1][2]转移而来,因为只要今天是P就可以;
// dp[i][1]一定由dp[i-1][0]转移而来,因为今天是L的情况下,昨天只能是P;
// dp[i][2]一定由dp[i-1][1]转移而来,因为两天都是L的情况下,昨天只能是L;

// p.s. 实在不会取模,就用long糊弄了


    private static final int MOD = 1000000007;
    public int checkRecord(int n) {
        long[][] dp = new long[n+1][3];
        dp[0][0] = 1;
        for(int i = 1; i <= n; i++) {
            dp[i][0] = sum(dp, i-1);
            dp[i][1] = dp[i-1][0];
            dp[i][2] = dp[i-1][1];
        }

        long sum1 = sum(dp, n);
        long sum2 = 0;
        for(int i = 0; i < n; i++) {
            sum2 += ((sum(dp, i) * sum(dp, n-1-i)) % MOD);
        }

        return (int) ((sum1 + sum2) % MOD);
    }

    private long sum(long[][] dp, int i) {
        return (((dp[i][0] + dp[i][1]) % MOD) + dp[i][2]) % MOD;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 总结

  • 分析出几种情况,然后分别对各个情况实现
微信 支付宝
最近更新
01
1686. 石子游戏VI Java
08-18
02
1688. 比赛中的配对次数 Java
08-18
03
1687. 从仓库到码头运输箱子 Java
08-18
更多文章>
Theme by Vdoing | Copyright © 2019-2025 JavaInterview.cn
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式