552. 学生出勤记录 II

  • 题目描述
  • 解题思路

题目描述

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

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

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

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

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

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/student-attendance-record-ii

示例1

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

示例2

输入:n = 1
输出:3

提示

  • 1 < = n < = 1 0 5 1 <= n <= 10^5 1<=n<=105

解题思路

本题考虑使用动态规划解决。由于可奖励的出勤记录要求是:缺勤次数少于 2 和连续迟到次数少于 3,因此动态规划的状态由总天数、缺勤次数和结尾连续迟到次数决定(由于不会记录连续迟到次数等于或多于 3 的情况,因此非结尾的连续迟到次数一定少于 3,只需要记录结尾连续迟到次数即可)。

定义 d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]表示前i天由j个‘A’且结尾有连续k个‘L’的可奖励的出勤记录的数量。其中 0 < = i < = n , 0 < = j < = 1 , 0 < = k < = 2 0<=i<=n, 0<=j<=1, 0<=k<=2 0<=i<=n,0<=j<=1,0<=k<=2。

当 i = 0 i=0 i=0时,没有任何出勤记录,此时“A”的数量和结尾连续“L”的数量一定为0,因此动态规划的边界情况是 d p [ 0 ] [ 0 ] [ 0 ] = 1 dp[0][0][0]=1 dp[0][0][0]=1。
当 1 < = i < = n 1<=i<=n 1<=i<=n时, d p [ i ] [ ] [ ] dp[i][][] dp[i][][]的值从 d p [ i − 1 ] [ ] [ ] dp[i-1][][] dp[i−1][][]的值转移得到,计算每个状态的值需要考虑第i天的出勤记录:

  • 如果第i天的出勤记录是“P”,则前i天和前 i − 1 i-1 i−1天的出勤记录相比,“A”的数量不变,结尾连续“L”的数量清零,因此对 0 < = j < = 1 0<=j<=1 0<=j<=1,有 d p [ i ] [ j ] [ 0 ] : = d p [ i ] [ j ] [ 0 ] + ∑ k = 0 2 d p [ i − 1 ] [ j ] [ k ] dp[i][j][0]:= dp[i][j][0]+\sum^{2}_{k=0} {dp[i-1][j][k]} dp[i][j][0]:=dp[i][j][0]+k=0∑2​dp[i−1][j][k]
  • 如果第i天的出勤记录是"A",则前i天和前i-1天的出勤记录相比,“A"的数量加1,结尾连续"L"的数量清零,此时要求前i-1天的出勤记录中"A"的数量必须是0,否则前i天的出勤记录至少有两个"A”,不满足可奖励的条件,因此有: d p [ i ] [ 1 ] [ 0 ] : = d p [ i ] [ 1 ] [ 0 ] + ∑ k = 0 2 d p [ i − 1 ] [ 0 ] [ k ] dp[i][1][0]:=dp[i][1][0]+\sum^{2}_{k=0} {dp[i-1][0][k]} dp[i][1][0]:=dp[i][1][0]+k=0∑2​dp[i−1][0][k]
  • 如果第i天的出勤记录是"L",则前i天和前i-1天的出勤记录相比,”A“的数量不变,结尾连续”L”的数量加1,此时要求前i-1天的出勤记录中的结尾连续"L"的数量不超过1,否则前i天的出勤记录的结尾至少有3个“L”,不满足可奖励条件,因此对 0 < = j < = 1 0<=j<=1 0<=j<=1和 1 < = k < = 2 1<=k<=2 1<=k<=2,有: d p [ i ] [ j ] [ k ] : = d p [ i ] [ j ] [ k ] + d p [ i − 1 ] [ j ] [ k − 1 ] dp[i][j][k]:=dp[i][j][k]+dp[i-1][j][k-1] dp[i][j][k]:=dp[i][j][k]+dp[i−1][j][k−1]

上述状态转移方程对于i=1也适用
计算长度为n的所有可奖励的出勤记录的数量,即为计算 d p [ n ] [ ] [ ] dp[n][][] dp[n][][]的所有元素之和。计算过程中需要将结果对 1 0 9 + 7 10^9+7 109+7取模。

根据上述思路,可以得到时间复杂度和空间复杂度都是O(N)的实现,代码如下:

# -*- coding: utf-8 -*-## -------------------------------------------------------------------------------
# Name:         552. 学生出勤记录 II
# Description:
# Author:       PANG
# Date:         2021/8/19
# -------------------------------------------------------------------------------
class Solution:def checkRecord(self, n: int) -> int:MOD = 10 ** 9 + 7# A 的数量,结尾连续 L 的数量dp = [[0, 0, 0], [0, 0, 0]]dp[0][0] = 1for i in range(1, n + 1):dpNew = [[0, 0, 0], [0, 0, 0]]# 以 P 结尾的数量for j in range(0, 2):for k in range(0, 3):dpNew[j][0] = (dpNew[j][0] + dp[j][k]) % MOD# 以 A 结尾的数量for k in range(0, 3):dpNew[1][0] = (dpNew[1][0] + dp[0][k]) % MOD# 以 L 结尾的数量for j in range(0, 2):for k in range(1, 3):dpNew[j][k] = (dpNew[j][k] + dp[j][k - 1]) % MODdp = dpNewtotal = 0for j in range(0, 2):for k in range(0, 3):total += dp[j][k]return total % MODif __name__ == '__main__':n = int(input())solution = Solution()print(solution.checkRecord(n))

【Leetcode】552. 学生出勤记录 II相关推荐

  1. LeetCode——552. 学生出勤记录 II(Student Attendance Record II)[困难]——分析及代码(Java)

    LeetCode--552. 学生出勤记录 II[Student Attendance Record II][困难]--分析及代码[Java] 一.题目 二.分析及代码 1. 动态规划 (1)思路 ( ...

  2. leetcode: 552. 学生出勤记录 II

    552. 学生出勤记录 II 来源:力扣(LeetCode) 链接: https://leetcode.cn/problems/student-attendance-record-ii/ 可以用字符串 ...

  3. LeetCode 552. 学生出勤记录 II(动态规划)

    文章目录 1. 题目 2. 解题 1. 题目 给定一个正整数 n,返回长度为 n 的所有可被视为可奖励的出勤记录的数量. 答案可能非常大,你只需返回结果mod 10^9 + 7的值. 学生出勤记录是只 ...

  4. 552. 学生出勤记录 II

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

  5. 力扣 -- 551. 学生出勤记录 I 、 552. 学生出勤记录 II

    目录 551. 学生出勤记录 一 .题目描述 二. 实现思路以及代码 552. 学生出勤记录 II 一 .题目描述 二. 实现思路以及代码 551. 学生出勤记录 一 .题目描述 给你一个字符串 s  ...

  6. Leetcode 552.学生出勤记录‖ 动态规划+容斥

    题目链接:传送门 可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤.迟到.到场).记录中只含下面三种字符: 'A':Absent,缺勤 'L':Late,迟到 'P':P ...

  7. C++Python描述 LeetCode 551. 学生出勤记录 I

    C++&Python描述 LeetCode 551. 学生出勤记录 I   大家好,我是亓官劼(qí guān jié ),在公众号.CSDN.GitHub.B站.华为开发者论坛等平台分享一些 ...

  8. Java实现 LeetCode 551 学生出勤记录 I(暴力大法好)

    551. 学生出勤记录 I 给定一个字符串来代表一个学生的出勤记录,这个记录仅包含以下三个字符: 'A' : Absent,缺勤 'L' : Late,迟到 'P' : Present,到场 如果一个 ...

  9. Leetcode每日一题-学生出勤记录 II(Student Attendance Record II)

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

最新文章

  1. C#快速整理代码格式
  2. pip安装mysql-python失败,并显示EnvironmentError:找不到mysql_config
  3. 【Java Web开发指南】Spring一些基础问题整理
  4. iOS开发-ViewController的生命周期和切换
  5. 开工啦,开工啦,2022开工了
  6. AWS实例上AMI和用户名的映射表
  7. 自己写的android apk反编译,获取Android自己写好了的apk以及反编译
  8. 华为再发行30亿元超短期融资券
  9. SAP 设置或取消仓库不参与MRP运算(转)
  10. SolrCloud集群的安装使用以及Zookeeper的介绍
  11. 剑指|| offer1整数除法
  12. Message、Handler、Message Queue、Looper、Thread之间的关系(未完成)
  13. Html5的测试总结
  14. [转] android自定义布局中的平滑移动
  15. 升级LINUX内核(支持8G内存)的命令
  16. mysql 批量插入(记录帖)
  17. 《Unity 3D人工智能编程》——2.2 子弹类
  18. c语言程序书写遵循的规则,C程序书写时应遵循的规则
  19. vscode中使用md文件
  20. 计算机原理及应用自测题4,自测题-微计算机原理-电子发烧友网站

热门文章

  1. 杭州国际服装城导航地图
  2. js-xlsx js处理excel 通过sheetJSON生成Excel文件
  3. Python爬虫学习之第七天---数据提取-lxml模块和Xpath使用
  4. Android发展历史
  5. c#关于DATATABLE,操作详解
  6. 操作系统实验——银行家算法
  7. 算力网络,到底是如何工作的?
  8. Springboot-jar包瘦身部署
  9. 主动学习(Active Learning)系列介绍(一)基本概念及应用场景
  10. Qt/C++编写地图综合应用48-地球模式、三维模式、地铁模式