最长的最美好子字符串 java版本 滑动窗口解法并配有注释
Posted tacit-lxs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最长的最美好子字符串 java版本 滑动窗口解法并配有注释相关的知识,希望对你有一定的参考价值。
最长的最美好子字符串
思路:
滑动窗口机制: 首先窗口的左右端都指向初始位置,遍历字符串进行滑动. 我们要得到的就是一个最长的窗口,里面所有字符种类同时包含每种字符的大小写.
这里窗口中的字符种类最小为1,最大为字符集的种类数max.因此我们可以设置窗口字符种类数从1到max,在此期间检查窗口滑动过程中能得到的最大最美好字符串并记录出现的索引及长度.
比如AaaAbB
设置字符种类为typeNum = 1,能得到的最长最美好字符串为AaaA
设置字符种类为typeNum = 2,能得到的最长最美好字符串为AaaAbB
代码
class Solution
private int maxPos;
private int maxLen;
public String longestNiceSubstring(String s)
this.maxPos = 0;
this.maxLen = 0;
int types = 0;
for(int i = 0;i < s.length();i++)
types |= 1 << (Character.toLowerCase(s.charAt(i)) - 'a');
// 得到字符串中的字符的种类数量
types = Integer.bitCount(types);
for(int i = 1;i <= types;i++)
check(s,i);
return s.substring(maxPos, maxPos + maxLen);
//在窗口中,维护一个记录大小写字母同时出现的字符种类数cnt和不同种类字符出现的次数total
public void check(String s, int typeNum)
int[] lowerCnt = new int[26];
int[] upperCnt = new int[26];
int cnt = 0;
// 开始时,左右边界都指向0,cnt,total都初始化为0
for(int l = 0,r = 0,total = 0;r < s.length();r++)
int idx = Character.toLowerCase(s.charAt(r)) - 'a';
//如果遍历到某个字符时,为大小写字母同时出现则cnt++
if(Character.isLowerCase(s.charAt(r)))
lowerCnt[idx]++;
if(lowerCnt[idx] == 1 && upperCnt[idx] > 0)
cnt++;
else
upperCnt[idx]++;
if(upperCnt[idx] == 1 && lowerCnt[idx] > 0)
cnt++;
//如果遍历到某个字符时,为一种新的字符集,total++
total += (lowerCnt[idx] + upperCnt[idx]) == 1 ? 1 : 0;
//当total > typeNum时,滑动窗口左端向右移动
while(total > typeNum)
idx = Character.toLowerCase(s.charAt(l)) - 'a';
total -= (lowerCnt[idx] + upperCnt[idx]) == 1 ? 1 : 0;
if(Character.isLowerCase(s.charAt(l)))
lowerCnt[idx]--;
if(lowerCnt[idx] == 0 && upperCnt[idx] > 0)
cnt--;
else
upperCnt[idx]--;
if(upperCnt[idx] == 0 && lowerCnt[idx] > 0)
cnt--;
l++;
//在滑动过程中更新maxPos和maxLen
if(cnt == typeNum && maxLen < r - l + 1)
maxPos = l;
maxLen = r - l + 1;
以上是关于最长的最美好子字符串 java版本 滑动窗口解法并配有注释的主要内容,如果未能解决你的问题,请参考以下文章
❤️思维导图整理大厂面试高频数组16: 最长湍流子数组的动态规划构建 和 滑动窗口解法, 力扣978❤️
❤️思维导图整理大厂面试高频数组16: 最长湍流子数组的动态规划构建 和 滑动窗口解法, 力扣978❤️
java 159.具有最多两个不同字符的最长子串(#1滑动窗口).java