📖本篇内容:leetcode每周.周赛第281场周赛 红海游戏专场 ~简单模拟 + 链表数据结构简单应用 + 优先队列的合理使用
📑 文章专栏:leetcode周赛打卡《周周打卡》
📆 最近更新:2022年2月 13日 leetcode每周.周赛第280场周赛 美团专场 还是有难度的 ~简单模拟 + 哈希奇偶计数 + 排序模拟遍历
🙊个人简介:一只二本院校在读的大三程序猿,本着注重基础,打卡算法,分享技术作为个人的经验总结性的博文博主,虽然可能有时会犯懒,但是还是会坚持下去的,如果你很喜欢博文的话,建议看下面一行~(疯狂暗示QwQ)
🌇 点赞 👍 收藏 ⭐留言 📝 一键三连 关爱程序猿,从你我做起
📖本文目录
🙊写在前面
🙊小付来喽,今天接着有更新周赛栏目了哦,今天小付第6次打单周赛
📆第281场周赛——2022-02-20
📝T1.6012.统计各位数字之和为偶数的整数个数
题目
给你一个正整数 num ,请你统计并返回 小于或等于 num 且各位数字之和为 偶数 的正整数的数目。
正整数的 各位数字之和 是其所有位上的对应数字相加的结果。
示例
示例1:
输入:num = 4
输出:2
解释:
只有 2 和 4 满足小于等于 4 且各位数字之和为偶数。
示例2:
输入:num = 30
输出:14
解释:
只有 14 个整数满足小于等于 4 且各位数字之和为偶数,分别是:
2、4、6、8、11、13、15、17、19、20、22、24、26 和 28 。
提示
1 <= num <= 1000
⭐思路 ⭐
一道简单的模拟题:
- 直接模拟即可
- 简单的位数求和问题
代码实现
class Solution {
public int countEven(int num) {
int res = 0;
for (int i = 2;i <= num;i++){
if (check(i))res++;
}
return res;
}
public boolean check(int num){
int checkNum = 0;
while (num > 0){
checkNum = checkNum + (num % 10);
num /= 10;
}
return checkNum % 2 == 0 ;
}
}
执行结果
📝T2.6013. 合并零之间的节点
题目
给你一个链表的头节点 head ,该链表包含由 0 分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足 Node.val == 0 。
对于每两个相邻的 0 ,请你将它们之间的所有节点合并成一个节点,其值是所有已合并节点的值之和。然后将所有 0 移除,修改后的链表不应该含有任何 0 。
返回修改后链表的头节点 head 。
示例
示例1:
输入:head = [0,3,1,0,4,5,2,0]
输出:[4,11]
解释:
上图表示输入的链表。修改后的链表包含:
- 标记为绿色的节点之和:3 + 1 = 4
- 标记为红色的节点之和:4 + 5 + 2 = 11
示例2:
输入:head = [0,1,0,3,0,2,2,0]
输出:[1,3,4]
解释:
上图表示输入的链表。修改后的链表包含:
- 标记为绿色的节点之和:1 = 1
- 标记为红色的节点之和:3 = 3
- 标记为黄色的节点之和:2 + 2 = 4
提示
列表中的节点数目在范围 [3, 2 * 105] 内
0 <= Node.val <= 1000
不 存在连续两个 Node.val == 0 的节点
链表的 开端 和 末尾 节点都满足 Node.val == 0
⭐思路 ⭐
本题思路以及考察点:
- 链表数据结构的合理应用
- 我们只需要记录如果当前的节点值不为0时,就可以直接将该节点的值合并入结果节点值中,
如果遍历到当前节点值为0时
,我们就需要跳过该节点
,并且重新加入一个结果节点并且初始化值为0重复上述操作。
代码实现
class Solution {
public ListNode mergeNodes(ListNode head) {
if (head == null) return null;
//用于遍历head节点的当前节点位置
ListNode cur = head;
//初始化结果链表,我们最后只需要返回当前res的res.next就可以了
ListNode res = new ListNode(0);
//作为记录res的起始节点位置
ListNode ans = res;
//如果当前节点还有后继节点就继续遍历
while (cur.next != null) {
//如果当前值为0时
if (cur.val == 0){
//需要调过当前为0的节点
cur = cur.next;
//并且创建新的结果节点
res.next = new ListNode(0);
//当前结果节点指向下一结果节点
res = res.next;
//跳出当前循环重复操作
continue;
}else {
//如果当前节点的值非0则直接并入值
res.val += cur.val;
}
//当前节点后移
cur = cur.next;
}
//返回结果节点的下一节点 这个res是带了头结点0的
return ans.next;
}
}
执行结果
📝T3.6014. 构造限制重复的字符串
题目
给你一个字符串 s 和一个整数 repeatLimit ,用 s 中的字符构造一个新字符串 repeatLimitedString ,使任何字母 连续 出现的次数都不超过 repeatLimit 次。你不必使用 s 中的全部字符。
返回 字典序最大的 repeatLimitedString 。
如果在字符串 a 和 b 不同的第一个位置,字符串 a 中的字母在字母表中出现时间比字符串 b 对应的字母晚,则认为字符串 a 比字符串 b 字典序更大 。如果字符串中前 min(a.length, b.length) 个字符都相同,那么较长的字符串字典序更大。
示例
示例1:
输入:s = "cczazcc", repeatLimit = 3
输出:"zzcccac"
解释:使用 s 中的所有字符来构造 repeatLimitedString "zzcccac"。
字母 'a' 连续出现至多 1 次。
字母 'c' 连续出现至多 3 次。
字母 'z' 连续出现至多 2 次。
因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。
该字符串是字典序最大的 repeatLimitedString ,所以返回 "zzcccac" 。
注意,尽管 "zzcccca" 字典序更大,但字母 'c' 连续出现超过 3 次,所以它不是一个有效的 repeatLimitedString 。
输入:s = "aababab", repeatLimit = 2
输出:"bbabaa"
解释:
使用 s 中的一些字符来构造 repeatLimitedString "bbabaa"。
字母 'a' 连续出现至多 2 次。
字母 'b' 连续出现至多 2 次。
因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。
该字符串是字典序最大的 repeatLimitedString ,所以返回 "bbabaa" 。
注意,尽管 "bbabaaa" 字典序更大,但字母 'a' 连续出现超过 2 次,所以它不是一个有效的 repeatLimitedString 。
提示
1 <= repeatLimit <= s.length <= 105
s 由小写英文字母组成
⭐思路 ⭐
这道题的思路可以对照第280场美团专场周赛的T2来:
- 这里用到了优先队列对我们的所有字符所对应的序号的数量进行记录
- 拼接字符串的时候要
先考虑到如果本次连续字符的数量增加之后,是否受到了
repeatLimit 的限制
,如果没有被限制 直接进行添加到结果字符串就ok了,如果被限制了,就必须通过优先队列找到次高字典序的第二个字符,来添加到咱们的结果字符串当中~
代码实现
class Solution {
public String repeatLimitedString(String s, int repeatLimit) {
// 用于存放每个字符的个数
int[] count = new int[26];
// 转化为字符数组
char[] ss = s.toCharArray();
// 逐一进行遍历,并且记录每个字符出现的次数
for(int i=0;i<ss.length;i++) {
// 对应字符位置上的个数 0-aCnt 1-bCnt
count[ss[i]-'a']++;
}
// 用于返回结果字符串
StringBuilder res = new StringBuilder();
// 按照字符在26个字符当中的顺序倒叙添加到优先队列当中
PriorityQueue<Integer> pq = new PriorityQueue<>((char1,char2)->char2-char1);
// 遍历每个字符的个数 如果存在字符就将其添加到优先队列当中
for(int i=0;i<26;i++) {
if(count[i]>0) pq.add(i);
}
int checkLimitNum = 0;
// 如果当前队列中还存在元素就继续构建结果字符串
while(pq.size()>0) {
// 取出当前字符的字符序号 例如 0-a 1-b ... 25-z
int maxCntCharIdx = pq.poll();
// 如果当前字符串 长度为0 或者 当前拼接的字符与上一个字符相同时 此时我们就要考虑repeatLimit的限制了
if(res.length() == 0 || (maxCntCharIdx+'a') == res.charAt(res.length()-1)) {
// 连续相同字符数量+1
checkLimitNum++;
} else {
// 反之重置为1
checkLimitNum=1;
}
// 然后对连续相同字符的限制进行判断
if(checkLimitNum<=repeatLimit) {
// 如果满足条件就直接将其加入到我们的结果字符串当中,并且字符数量减少
res.append((char)('a'+maxCntCharIdx));
count[maxCntCharIdx] --;
// 如果当前还有剩余数量的字符 我们还需要继续把他返回到优先队列中进行下次判断 直到用完该字符序号的所有字符
if(count[maxCntCharIdx]>0) pq.add(maxCntCharIdx);
} else {
// 反之到达了限制时 我们此时就要取出次高字典序的字符序号了 这和上周280周赛的第二题有点像
if(pq.size()>0) {
// 重新将连续相同字符数量置为1
checkLimitNum = 1;
// 取出次字典序高的字符序号
int subMaxCntCharIdx = pq.poll();
// 将次高的字符序号字符加入其中
res.append((char)('a'+subMaxCntCharIdx));
// 次高字符数量减少
count[subMaxCntCharIdx]--;
// 将我们之前取出的第一个最高数量的字符返回到优先队列当中,因为咱们没有用这个 重复操作
pq.add(maxCntCharIdx);
// 如果当前次高的字符数量还有剩余 则也将其返回到优先队列当中 重复操作
if(count[subMaxCntCharIdx]>0) pq.add(subMaxCntCharIdx);
} else {
// 返回结果
return res.toString();
}
}
}
return res.toString();
}
}
执行结果
🙊写在最后
小付打卡的第6场单周赛 2022-02-20
尽可能把会做的题 都做好 就可以了
本次周赛 对了三道题
卡在T4 ,逐步迈进三题选手了qwq
所以还是很不错的周赛体验
最后
每天进步点 每天收获点
愿诸君 事业有成 学有所获
如果觉得不错 别忘啦一键三连哦~