Leetcode 双周赛#32 题解
1540 K次操作转变字符串 #计数
题目链接
题意
给定两字符串\(s\)和\(t\),要求你在\(k\)次操作以内将字符串\(s\)转变为\(t\),其中第\(i\)次操作时,可选择如下操作:
选择字符串\(s\)中满足 \(1 \leq j \leq s.length\) 且之前未被选过的任意下标 \(j\)(下标从1开始),并将此位置的字符恰好切换 \(i\) 次。切换 1 次字符即用字母表中该字母的下一个字母替换它(字母表环状接起来,所以$'z'切换后会变成 \('a'\))。
请记住任意一个下标 j 最多只能被操作 1 次!!
不进行任何操作。
如果在不超过 k 次操作内可以把字符串 \(s\)转变成 \(t\) ,那么请你返回 true
,否则请你返回 false
分析
此题有不少的坑点,起初我没有注意到每个\(j\)只能操作一次,以为可以对\(j\)进行分解操作。事实上,读准题意后不是很难。我们要注意到,对于每一个\(i\),只能有一个字符可恰好获得\(i\)种操作。另外注意到两个串的长度是不一定相等的。
要使\(s[i]\)转变为\(t[i]\),最初可分为两种情况:
- 当\(s[i] \leq t[i]\),至少需要\(t[i] - s[i]\)次操作;
- 当\(s[i]>t[i]\),需要先将\(s[i]\)转变为\('z'\),再到达\(t[i]\),故至少需要$(t[i] - s[i]+26)Mod26 $次操作
两种情况可总结为最初至少需要$(t[i] - s[i]+26)Mod26 $次操作。
但注意,如果一个串中出现不止一个字符需要\(m(1 \leq m \leq 26)\)次的话,第一个这样的字符可以在第\(m\)次操作完成,但是,后面几个这样的字符(记为第\(x\)个),需要\(m+26*(x-1)\)次操作(跨越x次字母表)。比如说'aa'
转变为bb
,\(s[0]\)可以在一次操作(\(i=1\))完成,但是\(s[1]\)需要\(26+1\)次操作
class Solution {
public:
bool canConvertString(string s, string t, int k) {
if (s.length() != t.length()) return false;
vector<int> cnt(27);
for (int i = 0; i < s.length(); i++) {
int delt = (t[i] - s[i] + 26) % 26;
if (delt == 0) continue;
cnt[delt] ++; //如此的差值,出现次数+1
if (delt + (cnt[delt] - 1) * 26 > k) return false;
//一旦发现,操作次数大于k即说明结果为false
}
return true;
}
};
1541 平衡括号字符串的最少插入次数 #计数
题目链接
题意
给定括号字符串\(s\) ,它只包含字符 '('
和 ')'
。一个括号字符串被称为平衡的当它满足:
任何左括号
'('
必须对应两个连续的右括号'))'
。左括号
'('
必须在对应的连续两个右括号'))'
之前。
可在任意位置插入字符 '(' 和 ')' 使字符串平衡。现要返回让 s 平衡的最少插入次数。
样例
"()()))"
需要三次插入;"(()))(()))()())))"
需要四次插入
分析
这题看起来挺像括号匹配的,但此题如果只有栈去模拟的话,并不方便,因为你要考虑到')'
的出现次数,且要保证他们的出现是连续的!
为了保证平衡条件二,我们可以倒序遍历(当然正序遍历也可以,但这样需要同时记录两种括号的出现次数),遍历的过程中根据情况添补括号/记录右括号的出现次数。
class Solution {
public:
int minInsertions(string s) {
int right = 0, ans = 0;
for (int i = s.length() - 1; i >= 0; i--) {
if (s[i] == ')') {
if (i - 1 >= 0 && s[i - 1] == ')')
i--; //下一个右括号不用再管了
else
ans++; //补上一个右括号
right++; //一对连续的右括号
}
else {
if (right >= 1)
right--;//左一右二括号配对
else
ans += 2; //为左一括号补上两个右括号
}
}
return ans += right; //为剩下的几对右括号补上左括号
}
};
1542 找出最长的超赞子字符串 #前缀和 #状态压缩 #哈希表
题目链接
题意
给定仅由数字组成的字符串 s 。求 s 中最长的 超赞子字符串 的长度。其中"超赞子字符串"需满足满足下述两个条件:
- 该字符串是 s 的一个非空子字符串
- 进行任意次数的字符交换后,该字符串可以变成一个回文字符串
比如"9498331"
的长度为3,不是5
分析
审题,这题并不是在考察你经过任意次交换得到的回文串长度(见上方样例),而是要你找到一个区间长度,使得这样长度的子串交换后能够变为回文串。
我们容易想到一个由数字组成的回文串,它的所有组成字符中,至多只有一个字符出现次数为奇数,其余字符出现次数均为偶数。
既然我们只关心各字符出现的次数是偶数还是奇数,那么我们只需要用01序列的数据结构去记录每个数字出现的次数是偶数还是奇数,若为偶数,则记录为0
,反之为1
——\(1-10\)数字的状态由01串去记录,从而实现状态压缩。此外,我们通过01串去记录奇偶性,也有个好处,当我们增添字符时,状态变化可以通过status = status ^ (1<<i)
实现,偶+奇=奇,奇+奇=偶,与异或和的结果符合。
我们用哈希表记录每个状态最左出现的位置,设当前状态\(status_i\),①如果在之前已经出现过该状态(记录该状态为\(status_j\))。说明区间\([i, j]\)的字符出现次数都为偶数,即这个区间字符的出现并没有影响原来\(status_j\)的奇偶性。②如果在之前存在一个状态\(status_j\),它与\(status_i\)之间只有一个字符的出现次数的奇偶性是不同的,说明该字符的出现次数为奇数,影响了\(status_j\)的奇偶性,而其他字符出现次数的奇偶性没有变。我们的最新状态即是通过前缀和记录的位置来转移的。
提醒,如果使用map
的话会超时…
class Solution {
public:
int longestAwesome(string s) {
unordered_map<int, int> pre;
int status = 0, ans = 0;
pre[0] = 0;
for (int i = 1; i <= s.length(); i++) {
int num = s[i - 1] - '0';
status ^= (1 << num);
if (pre.count(status)) {
ans = max(ans, i - pre[status]);
}
else {
pre[status] = i;
}
for (int j = 0; j <= 9; j++) {
int prestatus = status ^ (1 << j); //对每一种数字翻转一次
if (pre.count(prestatus)) {
//说明翻转的状态在之前出现过,记位置为pos,pos到达i后,只影响了数字j的奇偶性
//说明pos->i所出现的字符,除了数字j以外,其他出现次数均为偶数
ans = max(ans, i - pre[prestatus]);
}
}
}
return ans;
}
};
Leetcode 双周赛#32 题解的更多相关文章
- LeetCode双周赛#33 题解
5480. 可以到达所有点的最少点数目 #贪心 题目链接 题意 给定有向无环图,编号从0到n-1,一个边集数组edges(表示从某个顶点到另一顶点的有向边),现要找到最小的顶点集合,使得从这些点出发, ...
- leetcode 双周赛9 进击的骑士
一个坐标可以从 -infinity 延伸到 +infinity 的 无限大的 棋盘上,你的 骑士 驻扎在坐标为 [0, 0] 的方格里. 骑士的走法和中国象棋中的马相似,走 “日” 字:即先向左(或右 ...
- leetcode 双周赛9 找出所有行中最小公共元素
给你一个矩阵 mat,其中每一行的元素都已经按 递增 顺序排好了.请你帮忙找出在所有这些行中 最小的公共元素. 如果矩阵中没有这样的公共元素,就请返回 -1. 示例: 输入:mat = [[,,,,] ...
- [每日一题2020.06.16] leetcode双周赛T3 5423 找两个和为目标值且不重叠的子数组 DP, 前缀和
题目链接 给你一个整数数组 arr 和一个整数值 target . 请你在 arr 中找 两个互不重叠的子数组 且它们的和都等于 target .可能会有多种方案,请你返回满足要求的两个子数组长度和的 ...
- LeetCode双周赛#36
1604. 警告一小时内使用相同员工卡大于等于三次的人 题目链接 题意 给定两个字符串数组keyName和keyTime,分别表示名字为keytime[i]的人,在某一天内使用员工卡的时间(格式为24 ...
- LeetCode双周赛#35
1589. 所有排列中的最大和 #差分 #贪心 题目链接 题意 给定整数数组nums,以及查询数组requests,其中requests[i] = [starti, endi] .第i个查询求 num ...
- LeetCode双周赛#34
5492. 分割字符串的方案数 #组合公式 #乘法原理 #区间分割 题目链接 题意 给定01二进制串\(s\),可将\(s\)分割为三个非空 字符串\(s_1,s_2,s_3\),即(\(s_1+s_ ...
- LeetCode All in One题解汇总(持续更新中...)
突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...
- Leetcode 10. 正则表达式匹配 - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...
随机推荐
- Jenkins配置,tomacat版本输出乱码和页面打开报404的问题
1.打开tomact下的startup.bat,tomcat版本控制台中文输出乱码,解决方法是去tomacat安装路径下的conf目录,打开logging.properties文件,将java.uti ...
- 基于 opencv 的图像处理入门教程
前言 虽然计算机视觉领域目前基本是以深度学习算法为主,但实际上很多时候对图片的很多处理方法,并不需要采用深度学习的网络模型,采用目前成熟的图像处理库即可实现,比如 OpenCV 和 PIL ,对图片进 ...
- Java学习的第三十三天
1.今天复习了第十二章的12.1的文件和12.2一直到12.2.4 2.没有问题 3.明天继续复习
- Scipy 学习第3篇:数字向量的距离计算
计算两个数字向量u和v之间的距离函数 1,欧氏距离(Euclidean distance) 在数学中,欧几里得距离或欧几里得度量是欧几里得空间中两点间"普通"(即直线)距离.使用这 ...
- python模块导入(包)
模块 关注公众号"轻松学编程"了解更多. 1.1. 模块的概述 在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里的代码就会越来越长,越来越不容易维护. 为了编写可维 ...
- Git--gitLab远程仓库分支代码回退的两种方案
事由:作为仓库的master,一时老眼昏花,把同事说的不合并看成了合并,直接合并了. 解决方法: 一.粗鲁的代码回退--直接在远程仓库合并 1. 在gitLab远程仓库中,基于想回退的代码的节点(co ...
- wamp&花生壳 在本地搭建自己的网站
1.wamp下载安装(2.49),按提示来. 唯一要注意的是默认端口为80,若80端口已被占用,修改apache配置文件httpd.conf(C:\wamp\bin\apache\apache2.4. ...
- 【SpringCloud】08.客户端负载均衡器:Ribbon
客户端负载均衡器:Ribbon Ribbon实现软负载均衡核心: 服务发现 :依据服务的名字,把该服务下所有的实例都找出来 服务选择规则:依据规则策略,如果从多个实例中,选出有效的服务 服务监听:检测 ...
- 9个JavaScript日常开发小技巧
1.生成指定范围的数字 在某些情况下,我们会创建一个处在两个数之间的数组.假设我们要判断某人的生日是否在某个范围的年份内,那么下面是实现它的一个很简单的方法 1 2 3 4 5 6 let start ...
- MySQL全面瓦解9:查询的排序、分页相关
概述 数据库中的数据直接呈现出来一般不是我们想要的,所以我们上两节演示了如何对数据进行过滤的方法.除了对数据进行过滤, 我们可能还需要对数据进行排序,比如想从列表中了解消费最高的项,就可能需要对金额字 ...