题目描述
给定一个字符串,请找出最长的不包含重复字符的子串。
请注意子串和子序列的区别:子串一定是连续的一段
子序列不一定是连续的一段,但下标要求是递增的样例
给定 "abcabcbb",答案是"abc",长度是3.
给定 "bbbbb",答案是"b",长度是1.
给定 "pwwkew",答案是"wke",长度是3.
分析:
(双指针扫描) O(n) 为了代码的简洁,把String s放到char[ ] c中;
1、定义两个指针 i,j,(i<=j),表示当前扫描到的子串是 [ i , j ](闭区间)。扫描过程中维护一个哈希表HashMap<Character,Integer> ,表示 [ i , j ]中每个字符出现的次数。
2、线性扫描时,每次循环的流程如下:
- 指针 j 向后移一位, 同时将哈希表中 key 为chars[ j ]的value值计数加一;
- 假设 j 向后移动之前的区间 [ i , j ] 中没有重复字符,则 j 移动后,只有 chars[ j ] 可能出现2次。因此我们不断向后移动 i,直至区间 [ i , j ] 中 chars[ j ] 的个数等于1为止;
复杂度分析:由于 i , j 均最多增加n次,且哈希表的插入和更新操作的复杂度都是 O(1),因此,总时间复杂度 O(n)
Java实现:
import java.util.HashMap;
/**
* @ClassName:Solution
* @description:
* @Author: why
* @Date: 2019/4/20
*/
public class Solution {
public int lengthOflongestSubString(String s){
int res=0;
char[] chars=s.toCharArray();
HashMap<Character,Integer>map=new HashMap<>(16);
for (int i=0,j=0;j<chars.length;j++){
//value+1
if (map.get(chars[j])!=null){
map.put(chars[j],map.get(chars[j])+1);
}else {
map.put(chars[j],1);
}
if (map.get(chars[j])>1){
while (i<j){
map.put(chars[i],map.get(chars[i])-1);
i++;
if (map.get(chars[j])==1){
break;
}
}
}
res=Math.max(res,j-i+1);
}
return res;
}
}
测试结果:
987 / 987 个通过测试用例 | 状态:通过 |
执行用时:43 ms | 提交时间:0 分钟之前 |