LeetCode 551. 学生出勤记录 I /552. 学生出勤记录 II(动态规划)/345. 反转字符串中的元音字母(set加入元素的方法)
Posted Zephyr丶J
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 551. 学生出勤记录 I /552. 学生出勤记录 II(动态规划)/345. 反转字符串中的元音字母(set加入元素的方法)相关的知识,希望对你有一定的参考价值。
551. 学生出勤记录 I
2021.8.17 每日一题
题目描述
给你一个字符串 s 表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:
‘A’:Absent,缺勤
‘L’:Late,迟到
‘P’:Present,到场
如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:
按 总出勤 计,学生缺勤(‘A’)严格 少于两天。
学生 不会 存在 连续 3 天或 3 天以上的迟到(‘L’)记录。
如果学生可以获得出勤奖励,返回 true ;否则,返回 false 。
示例 1:
输入:s = “PPALLP”
输出:true
解释:学生缺勤次数少于 2 次,且不存在 3 天或以上的连续迟到记录。
示例 2:
输入:s = “PPALLL”
输出:false
解释:学生最后三天连续迟到,所以不满足出勤奖励的条件。
提示:
1 <= s.length <= 1000
s[i] 为 ‘A’、‘L’ 或 ‘P’
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/student-attendance-record-i
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
class Solution {
public boolean checkRecord(String s) {
int l = s.length();
int countA = 0;
for(int i = 0; i < l; i++){
if(s.charAt(i) == 'A')
countA++;
if(countA >= 2)
return false;
int countL = 0;
int t = i;
while(t < l && s.charAt(t) == 'L'){
t++;
countL++;
if(countL == 3)
return false;
}
if(t > i)
i = t - 1;
}
return true;
}
}
要学会用API
class Solution {
public boolean checkRecord(String s) {
return !s.contains("LLL") && !(s.indexOf('A') < s.lastIndexOf('A'));
}
}
552. 学生出勤记录 II
2021.8.18 每日一题
题目描述
可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:
‘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 <= 10^5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/student-attendance-record-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
动态规划:
刚开始我是这样定义状态方程的:
dp[i][0]表示之前没有A,当前为A的时候,获得出勤奖励的情况数量,如果能从这个状态转移,就说明有A了
dp[i][1]表示当前为L的时候,获得出勤奖励的情况数量
dp[i][2]表示当前为两个连续的L的时候,获得出勤奖励的情况数量
dp[i][3]表示当前为P的时候,获得出勤奖励的情况数量
然后发现有没有A没办法搞,所以想是不是要在每个状态又定义一个维度表示当前是否有A,即
dp[i][0][0]表示当前为P的时候,并且没有A,获得出勤奖励的情况数量
dp[i][0][1]表示当前为P的时候,并且有A,获得出勤奖励的情况数量
dp[i][1][0]表示当前为L的时候,并且没有A的情况下,获得出勤奖励的情况数量
dp[i][1][1]表示当前为L的时候,并且有一个A的情况下,获得出勤奖励的情况数量
dp[i][2][0]表示当前为两个连续的L的时候,没有A,获得出勤奖励的情况数量
dp[i][2][1]表示当前为两个连续的L的时候,有A,获得出勤奖励的情况数量
发现还是不太对,因为那如果当前是A的话,当前为P的情况该怎么转移呢,所以应该定义成有没有L
dp[i][0][0]表示当前连续L的个数为0的时候,并且没有A,获得出勤奖励的情况数量
dp[i][0][1]表示当前连续L的个数为0的时候,并且有A,获得出勤奖励的情况数量
dp[i][1][0]表示当前为L的时候,并且没有A的情况下,获得出勤奖励的情况数量
dp[i][1][1]表示当前为L的时候,并且有一个A的情况下,获得出勤奖励的情况数量
dp[i][2][0]表示当前为两个连续的L的时候,没有A,获得出勤奖励的情况数量
dp[i][2][1]表示当前为两个连续的L的时候,有A,获得出勤奖励的情况数量
class Solution {
public int checkRecord(int n) {
//动规,三个状态
//dp[i][0]表示之前没有A,当前为A的时候,获得出勤奖励的情况数量,如果能从这个状态转移,就说明有A了
//dp[i][1]表示当前为L的时候,获得出勤奖励的情况数量
//dp[i][2]表示当前为两个连续的L的时候,获得出勤奖励的情况数量
//dp[i][3]表示当前为P的时候,获得出勤奖励的情况数量
//dp[i][0]表示之前没有A,当前为A的时候,获得出勤奖励的情况数量,如果能从这个状态转移,就说明有A了
//不行
//dp[i][0][0]表示当前连续L个数为0的时候,并且没有A,获得出勤奖励的情况数量
//dp[i][0][1]表示当前连续L个数为0的时候,并且有A,获得出勤奖励的情况数量
//dp[i][1][0]表示当前为L的时候,并且没有A的情况下,获得出勤奖励的情况数量
//dp[i][1][1]表示当前为L的时候,并且有一个A的情况下,获得出勤奖励的情况数量
//dp[i][2][0]表示当前为两个连续的L的时候,没有A,获得出勤奖励的情况数量
//dp[i][2][1]表示当前为两个连续的L的时候,有A,获得出勤奖励的情况数量
int MOD = (int)1e9 + 7;
int[][][] dp = new int[n + 1][3][2];
//初始化,表示第一个位置,可以放任何一个字母
dp[1][0][0] = 1; //第一个为P
dp[1][0][1] = 1; //第一个为A
dp[1][1][0] = 1; //第一个为L
dp[1][1][1] = 0;
//dp[0][0][0] = 1;
//状态转移
for(int i = 2; i <= n; i++){
//如果当前为P,可以从其他任何A数量相同的状态转移
for(int j = 0; j < 3; j++){
for(int k = 0; k < 2; k++){
dp[i][0][k] = (dp[i][0][k] + dp[i - 1][j][k]) % MOD;
}
}
//如果当前为L,那么状态就是之前一天L少一个的状态
for(int j = 1; j < 3; j++){
for(int k = 0; k < 2; k++){
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j - 1][k]) % MOD;
}
}
//如果当前为A,那么就是由之前没有A的状态
for(int j = 0; j < 3; j++){
dp[i][0][1] = (dp[i][0][1] + dp[i - 1][j][0]) % MOD;
}
}
int res = 0;
for(int j = 0; j < 3; j++){
for(int k = 0; k < 2; k++){
res = (res + dp[n][j][k]) % MOD;
}
}
return res;
}
}
矩阵快速幂就不写了,赶时间哈哈
345. 反转字符串中的元音字母
2021.8.19 每日一题
题目描述
编写一个函数,以字符串作为输入,反转该字符串中的元音字母。
示例 1:
输入:“hello”
输出:“holle”
示例 2:
输入:“leetcode”
输出:“leotcede”
提示:
元音字母不包含字母 “y” 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-vowels-of-a-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
幸亏我还记得原因字母是啥。。
双指针反转,中间写那段有点快排的感觉了
class Solution {
public String reverseVowels(String s) {
//元音字母,我记得是aeiou,如果还有大写,也加进去
//然后我其实没看懂它这个反转是啥意思,意思是左右翻转呗
int l = s.length();
char[] cc = s.toCharArray();
int left = 0;
int right = l - 1;
Set<Character> set = new HashSet<>();
set.add('a');
set.add('e');
set.add('i');
set.add('o');
set.add('u');
set.add('A');
set.add('E');
set.add('I');
set.add('O');
set.add('U');
while(left < right){
while(left < right && !set.contains(cc[left])){
left++;
}
while(left < right && !set.contains(cc[right])){
right--;
}
char c = cc[left];
cc[left] = cc[right];
cc[right] = c;
left++;
right--;
}
return new String(cc);
}
}
我这里哈希写的好烦,看下官解,就是优雅
public boolean isVowel(char ch) {
return "aeiouAEIOU".indexOf(ch) >= 0;
}
再找几个:
用列表建哈希,秒
private final static HashSet<Character> vowel = new HashSet<>(
Arrays.asList('a','e','i','o','u','A','E','I','O','U')
);
直接创建哈希时添加
Set<Character> vowels = new HashSet<>(){{
add('a');
add('e');
add('i');
add('o');
add('u');
add('A');
add('E');
add('I');
add('O');
add('U');
}};
switch
private boolean isVowel(char c) {
switch(c) {
case 'a' :
case 'e' :
case 'i' :
case 'o' :
case 'u' :
case 'A' :
case 'E' :
case 'I' :
case 'O' :
case 'U' :
return false;
}
return true;
}
三叶姐好秀:
直接创建静态的变量,在所有测试用例的时候这个变量就仅仅被创建一次
注意:这里用数组模拟哈希减的是空字符 ’ ’
static boolean[] hash = new boolean[128];
static char[] vowels = new char[]{'a','e','i','o','u'};
static {
for (char c : vowels) {
hash[c - ' '] = hash[Character.toUpperCase(c) - ' '] = true;
}
}
static char[] vowels = new char[]{'a','e','i','o','u'};
static Set<Character> set = new HashSet<>();
static {
for (char c : vowels) {
set.add(c);
set.add(Character.toUpperCase(c));
}
}
以上是关于LeetCode 551. 学生出勤记录 I /552. 学生出勤记录 II(动态规划)/345. 反转字符串中的元音字母(set加入元素的方法)的主要内容,如果未能解决你的问题,请参考以下文章
Leetcode刷题100天—551.学生出勤记录I(字符串)—day12
LeetCode 551 学生出勤记录I[选择 字符串] HERODING的LeetCode之路