【不定滑窗】2023C-求满足条件的最长子串的长度
【不定滑窗】2023C-求满足条件的最长子串的长度
题目描述与示例
本题练习地址:https://www.algomooc.com/problem/P3204
题目描述
给定一个字符串,只包含字母和数字,按要求找出字符串中的最长 (连续)子串的长度,字符串本身是其最长的子串,子串要求:
- 只包含
1
个字母(a~z,A~Z)
,其余必须是数字 - 字母可以在子串中的任意位置;
如果找不到满足要求的子串,如全是字母或全是数字,则返回-1
。
输入描述
字符串(只包含字母和数字)
输出描述
最长子串的长度
示例一
输入
abC124ACb
输出
4
说明
满足条件的最长子串是C124
或者124A
,长度都是4
示例二
输入
a5
输出
2
说明
字符串自身就是满足条件的子串,长度为2
示例三
输入
aBB9
输出
2
说明
满足条件的子串为B9
,长度为2
示例四
输入
abcdef
输出
-1
说明
没有满足要求的子串,返回-1
解题思路
本题属于典型的不定滑窗问题。我们可以维护两个计数变量alpha_num
和digit_num
用来分别表示窗口中的字母和数字个数,滑窗三问三答将围绕这两个变量来进行。
滑窗三问
**Q1:**对于每一个右指针right
所指的元素ch
,做什么操作?
Q2:什么时候要令左指针left
右移?left
对应的元素做什么操作?while
中的循环不变量是什么?
**Q3:**什么时候进行ans
的更新?
滑窗三答
**A1:**根据ch
的类型(数字/字母),修改对应的计数变量(alpha_num
/digit_num
)。
**A2:**窗口中字母的个数等于2
,即alpha_num = 2
,left
指针右移,同时根据右移时经过的元素类型修改计数变量,直到alpha_num = 1
。
A3:alpha_num = 1
且digit_num > 0
,说明窗口中仅存在一个字母和若干数字,此时可以更新答案ans
。
代码
Python
# 题目:2023C-求满足条件的最长子串的长度
# 分值:100
# 作者:许老师-闭着眼睛学数理化
# 算法:不定滑窗
# 代码看不懂的地方,请直接在群上提问
# 输入
s = input()
# 计数变量alpha_num:记录窗口中字母个数的变量
alpha_num = 0
# 计数变量digit_num:记录窗口中数字个数
digit_num = 0
# 答案变量
ans = -1
# 左指针
left = 0
# 遍历s中的每一个字符ch
for right, ch in enumerate(s):
# A1:根据ch是数字还是字母,修改对应的计数变量
if ch.isdigit():
digit_num += 1
elif ch.isalpha():
alpha_num += 1
# A2:如果窗口中的字母个数为2,则左指针需要右移
# 需要根据左指针所指元素的种类,修改计数变量
if alpha_num == 2:
while alpha_num == 2:
if s[left].isdigit():
digit_num -= 1
elif s[left].isalpha():
alpha_num -= 1
left += 1
# A3:如果窗口中字母个数为1,数字个数大于0,则可以更新答案
# 此时窗口长度为digit_num+1,或者right-left+1也可
if alpha_num == 1 and digit_num > 0:
ans = max(ans, digit_num + 1)
print(ans)
Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String s = scanner.nextLine();
int alphaNum = 0;
int digitNum = 0;
int ans = -1;
int left = 0;
for (int right = 0; right < s.length(); right++) {
char ch = s.charAt(right);
if (Character.isDigit(ch)) {
digitNum++;
} else if (Character.isLetter(ch)) {
alphaNum++;
}
if (alphaNum == 2) {
while (alphaNum == 2) {
if (Character.isDigit(s.charAt(left))) {
digitNum--;
} else if (Character.isLetter(s.charAt(left))) {
alphaNum--;
}
left++;
}
}
if (alphaNum == 1 && digitNum > 0) {
ans = Math.max(ans, digitNum + 1);
}
}
System.out.println(ans);
}
}
C++
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
getline(cin, s);
int alphaNum = 0;
int digitNum = 0;
int ans = -1;
int left = 0;
for (int right = 0; right < s.length(); right++) {
char ch = s[right];
if (isdigit(ch)) {
digitNum++;
} else if (isalpha(ch)) {
alphaNum++;
}
if (alphaNum == 2) {
while (alphaNum == 2) {
if (isdigit(s[left])) {
digitNum--;
} else if (isalpha(s[left])) {
alphaNum--;
}
left++;
}
}
if (alphaNum == 1 && digitNum > 0) {
ans = max(ans, digitNum + 1);
}
}
cout << ans << endl;
return 0;
}
时空复杂度
时间复杂度:O(``N``)
。需要遍历字符串s
中的每一个字符ch
。
空间复杂度:O(``1``)
。