最长的最美好子字符串 java版本 滑动窗口解法并配有注释

本文详细介绍了如何使用滑动窗口机制来寻找一个字符串中最长的最美好子字符串,即子字符串中所有字符都有其大小写形式。通过遍历字符串并维护窗口内的字符种类计数,动态调整窗口大小,最终找到满足条件的最长子串,并返回其起始位置和长度。代码示例展示了具体的实现过程。
摘要由CSDN通过智能技术生成

最长的最美好子字符串

在这里插入图片描述

思路:

滑动窗口机制: 首先窗口的左右端都指向初始位置,遍历字符串进行滑动. 我们要得到的就是一个最长的窗口,里面所有字符种类同时包含每种字符的大小写.

这里窗口中的字符种类最小为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;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tacit-lxs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值