题目描述如下:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
这一题用暴力算法遍历也可以, 但是时间会超过leetcode的要求.
读题可以总结题目有如下特点:
- 输出结果在原字符串中是连续排列的
- 每次需要读取的只在头/尾部, 中间部分内容提供比较时用
这时候考虑用滑动窗口的方式就可以显著地减少操作次数.
代码如下:
import java.util.*;
public class demo {
public static void main(String[] args) {
String str = "pwwkew";
char[] ch = str.toCharArray();
// map用于存放已有字符的指向地址, 主要使用到map的key的唯一性
Map<Character, Integer> map = new HashMap<>();
// index为指向尾部的游标, 初始的时候在0之前.
int index = -1;
int maxLen = 0;
// i为指向头部的游标, 不断遍历前进
for(int i =0; i < ch.length; i++){
// 加入之前有走到过的字符就会存在于map中, key为字符, value为该字符最后一次出现的位置
if(map.containsKey(ch[i])){
// 此处取最大值是为了判断当前重复值是否再当前窗体内, 如果在当前窗体内则把尾巴游标缩进到map.get(ch[i]), 否则则维持上一次尾部位置
index = Math.max(index, map.get(ch[i]));
}
// 每次移动头部都计算长度, 注意我们的游标尾部是从-1开始的, 而且index指向的是上一个重复的字符所在位置, 所以只需要i-index, 不需要再+1
maxLen = Math.max(maxLen, i-index);
// 把最后一次出现这个坐标放入map
map.put(ch[i], i);
}
System.out.println(maxLen);
}
}
以上这段代码需要注意的是尾部游标的位置是包含重复字符的位置的, 所以初始值是-1, 求最大长度的时候只需要i-index(头-尾), 不需要再+1.