当前位置: 首页 > news >正文

1542. 找出最长的超赞子字符串

1. 题目

1542. 找出最长的超赞子字符串

2. 解题思路

首先来理解一下题目,“超赞字符串”:一个字符串可以重新排序得到一个回文字符串。
那么想达到这个结果,必须有一个前置条件那就是:对每个字符的出现次数进行计数,若出现奇数次的字符的数量不超过 1,则该字符串可以重新排列成回文。
举例说明:
image.png
因为只关心一个字符出现的次数是奇是偶,因此不需要真正的计数,可用1表示该数字出现了奇数次,0 表示该数字出现了偶数次,然后数字范围为0-9一共10个数字。所以使用一个长度为 10 的二进制数(即一个整数的二进制表示)来记录 0-9 每个数字的出现奇偶性。
(即status 是一个 10 位的二进制数,每一位(从低位到高位)分别对应数字 09。如果某一位是 1,表示该位对应的数字出现了奇数次;如果某一位是 0,表示该位对应的数字出现了偶数次。)

1、我们用 status= status^(1<<i) 来达到记录这个数字i的奇偶性的情况。

[!NOTE] status= status^(1<<i)是什么意思呢?
我们直接来举个例子看看,假设有个字符串"24214",那我们初始化status:0000000000 十位二进制数,都为0.
我们处理第一个数字2 那么status = status^(1<<2),拆解一下1<<2 将1向左移2位,得到0000000100,然后将其与原来的status0000000000进行异或(相同为0,不同为1),得到0000000100,这就代表现在的status下,2这个数字出现了奇数次,其余的数字出现了偶数次

2、用一个map来维护每个 status 出现的最早的位置

[!NOTE] 对于2的扩展
综合上面两种操作其实可以得到两个结论 :
1、 如果 status2 和 status1 相同,这意味着从 map.get(status1) 到 map.get(status2) 之间的字符串中,所有数字的奇偶性都没有发生变化。换句话说,在这个区间内,每个数字的出现次数要么都增加了偶数次,要么都减少了偶数次。因此,在这个区间 (map.get(status1), map.get(status2)] 中(注意区间左开右闭),所有数字的出现次数都是偶数次。
例如:
假设我们有字符串 s = "3242415",我们用一个长度为 10 的二进制数来表示状态,每一位对应数字 0-9 的奇偶性。 初始状态status = 0000000000
image.png
2、如果 status2 和 status1 只差一位不同,那么区间 (map.get(status1),map.get(status2)] 中(注意区间左开右闭)有一个数字出现了奇数次,其余数字都出现了偶数次,满足超赞的条件。

然后在满足条件的情况下计算超赞字串的长度,以上面的例子为例,长度即为当前status的位置-第一次出现相同status的位置,即4-0=4 超赞子字符串(为了方便理解,将其顺序重新排列为回文串)的"2442"的长度为4。
根据上述逻辑去遍历处理字符串即可。

3. 代码

3.1. 注意点

[!NOTE] 1、为啥在for循环中不光有个if (!map.containsKey(cur))还要再有个内部循环for (int i = 0; i < 10; i++)
根据我们的解题思路我们可以得知,有两种情况都会出现超赞子字符串,
1-所有数字出现次数都为偶数,这个情况在外层for循环中用if (!map.containsKey(cur))判断就能达到目的。
2-只有一个数字出现奇数次,其余数字出现偶数次,这个情况就需要在内部再来一次for循环去判断了,内部循环的目的是检查通过切换单个数字的奇偶性是否可以找到一个更长的超赞子字符串。
在遍历当前字符的时候需要同时考虑这两种情况,才能取到正确的答案!

[!NOTE] 2、检查是否只有一个数字出现奇数次,其余数字出现偶数次是怎么做的
内部循环遍历数字 0 到 9,通过 cur ^ (1 << i) 来检查如果我们假设数字 i 的奇偶性发生改变(从偶数变奇数或从奇数变偶数),那么当前的状态 cur 变成了 next。通过这种方式,我们可以检查在当前状态下,有没有可能使得其他数字的出现次数都是偶数,只有一个数字的出现次数是奇数。

3.2. 完整代码

class Solution {public int longestAwesome(String s) {HashMap < Integer, Integer > map = new HashMap < > ();int cur = 0; // 当前状态int ans = 1; // 记录最长超赞子字符串的长度map.put(cur, -1); // 初始状态,所有数字出现偶数次for (int c = 0; c < s.length(); c++) {int ch = s.charAt(c) - '0'; // 当前字符转换为数字// 更新状态cur = cur ^ (1 << ch); // 切换对应数字的奇偶性// 检查是否只有一个数字出现奇数次,其余数字出现偶数次for (int i = 0; i < 10; i++) {int next = cur ^ (1 << i); // 改变第 i 位的奇偶性if (map.containsKey(next)) {// 更新最长超赞子字符串的长度ans = Math.max(ans, c - map.get(next));}}// 检查当前状态是否存在于 map 中if (!map.containsKey(cur)) {map.put(cur, c); // 记录当前状态的首次出现位置} else {ans = Math.max(ans, c - map.get(cur)); // 更新长度}}return ans; // 返回结果}
}

http://www.mrgr.cn/news/33648.html

相关文章:

  • Snap 发布新一代 AR 眼镜,有什么特别之处?
  • PCB设计中百兆以太网是否需要差分布线?
  • 皮科医生对网红药膏的说明
  • 7. 无线网络安全
  • 【.NET 8 实战--孢子记账--从单体到微服务】--特别说明
  • 以太坊客户端Geth的介绍与搭建
  • 基于SpringBoot+Vue+MySQL的校园一卡通系统
  • ECharts基础使用方法 ---vue
  • 都市女生热衷找搭子的原因?只因对生活的热爱和追求
  • vscod django项目--编辑用户信息
  • js进阶——什么是提升
  • MySQL RANGE 分区规则
  • 求两个数二进制中不同位的数
  • UML——统一建模语言
  • Git 向远程仓库推送更改时加注释
  • OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【文件系统】上
  • 【comfyUI工作流】一键生成专属欧美漫画!
  • 视频怎么剪切掉一部分?6款视频剪切软件,零基础也能快速学会!
  • 【Java笔记】第12章:常用类
  • 基于单片机的无线宠物自动喂食系统设计