题目描述:给定一个字符串 s
,请你找出其中不含有重复字符的 最长字符串 的长度。
示例:
题目分析:在字符串中找到不含有重复字符的最长的字符串,并且输出它的长度。很多同学的第一反应都是用循环去遍历字符串中的每一个字符,然后用if条件判断语句去判断第i个字符是否与第i+1个字符相同,这样的方法十分繁琐很容易就把自己给绕晕,增加编码难度以及代码量,且很难达到题目要求的。
这个问题本质上是一个经典的滑窗问题,所以我们采用滑窗问题的思想去解决就可以。
滑窗问题思想:将子数组(子字符串)理解成一个滑动的窗口,然后将这个窗口在数组上滑动,在窗口滑动的过程中,左边会出一个元素,右边会进一个元素,然后只需要计算当前窗口内的元素值即可。
滑窗算法思路:
- 使用双指针中的左右指针技巧,初始化 left = right = 0,把索引闭区间 [left, right] 称为一个。[窗口]
- 先不断地增加 right 指针扩大窗口 [left, right],直到窗口符合要求
- 停止增加 right,转而不断增加 left 指针缩小窗口 [left, right],直到窗口中的字符串不再符合要求。同时,每次增加 left,我们都要更新一轮结果。
- 重复第 2 和第 3 步,直到 right 到达尽头。
本题滑窗算法:
public int lengthOfLongestSubstring(String s) {
int[] arr = new int[128];
int left = 0;
int ans = 0;
for (int i = 0; i < s.length(); i++) {
//如果窗口中有字符重复
//向右滑动,并去除被窗口跳过的字符,直到窗口中无重复字符
while (arr[s.charAt(i)] != 0) {
arr[s.charAt(left++)]--;
}
// 记录窗口右边界滑动时新增字符
arr[s.charAt(i)]++;
// 每次取最大窗口长度
ans = Math.max(ans, i - left+1 );
}
return ans;
}
i-left+1是因为下标从0开始,题目要求输出的不重复字符串的最大长度,所以要+1.
完整代码:
package Practice;
import java.util.*;
public class demo1 {
public static void main(String args[]){
Scanner in=new Scanner(System.in);
String s=in.nextLine();
solution k=new solution();
int a=k.lengthOfLongestSubstring(s);
System.out.print(a);
}
}
class solution{
public int lengthOfLongestSubstring(String s) {
int[] arr = new int[128];
int left = 0;
int ans = 0;
for (int i = 0; i < s.length(); i++) {
//如果窗口中有字符重复
//向右滑动,并去除被窗口跳过的字符,直到窗口中无重复字符
while (arr[s.charAt(i)] != 0) {
arr[s.charAt(left++)]--;
}
// 记录窗口右边界滑动时新增字符
arr[s.charAt(i)]++;
// 每次取最大窗口长度
ans = Math.max(ans, i - left+1 );
}
return ans;
}
}
IDEA中的运行结果: