给定一个字符串,请找出其中无重复字符的最长子字符串。
例如,在"abcabcbb"
中,其无重复字符的最长子字符串是"abc"
,其长度为 3
。
对于,"bbbbb"
,其无重复字符的最长子字符串为"b"
,长度为1
。
public class Solution {
/** 遍历该字符串,每遍历一个字母时,利用map去找该字母最近一次出现是什么时候
* 中间这一段便是无重复字符的字符串。
* 算法思想:两次循环得到所有的子串,用hash判断是否重复。
代码
代码中需要注意的地方:
1.以字符对应的ASCII码作为hash值,visit[str[i]]=0,说明str[i]这个字符还没有出现过,=1说明有重复。
2.在每次内层循环重新开始的时候,都要将visit初始化为0,每次内层循环求的是str[i...j]之间的最长子串,要判断他们之间是否有重复,所以要确保i...j这个范围内的visit都没初始化为0了,否则出现i...j之间的字符和这个范围之外的字符重复就会导致结果出错。
用一个256个元素的整形数组表示一个字符串中是否含有某个字符。
a~b分别映射到数组元素0~25。
用两个指针分别指向字符串的第一个和第二个元素,用第二个指针从左往右扫描字符串。
每扫描一个字符,根据数组中对应的值来判断这个字符是否已经出现。
如果没出现,则继续扫描,同时更新已知不相同子串的最大长度。
如果出现过,那么向右移动第一个指针,直到刚才重复的那个字符不再重复,然后继续上面的工作。
http://www.cnblogs.com/haozhengfei/p/d0906ebc98f7b6eaecb3ecd738dc78ac.html
*/
public int lengthOfLongestSubstring(String A){
}
public int lengthOfLongestSubstring(String A) {
if(A == null || A.length() == 0)return 0;
//map 统计A中每种字符之前出现的位置
Map<Character, Integer> map = new HashMap<Character, Integer>();
//len代表以s[i-1]结尾的情况下,最长无重复子串的长度
int[] len = new int[A.length()];
char[] charArr = A.toCharArray();
//从头到尾遍历charArr,统计出以每个字符为当前位置的向前最长无重复子串的长度
for(int i=0; i<A.length(); i++){
Integer lastPosOfChar = map.get(charArr[i]);//获取键对应的值,即下标
if(lastPosOfChar == null){//说明当前字符第一次出现
//更新最长无重复子串的长度
len[i] = i == 0 ? 1 : len[i-1] + 1;
//map记录当前字符出现的位置,即存入
map.put(charArr[i], i);
}
else{//当前字符不是第一次出现(既然不是第一次出现,那也不是在第一个位置),也就是之前出现过该字符
//获取前一个字符最长无重复子串的长度
int aPos = lastPosOfChar + 1;
int unRepeatLen = len[i-1];
int bPos = i - unRepeatLen;
if(aPos >= bPos){
//当前位置的最长无重复子串长度
len[i] = i - aPos + 1;
}
else{
//当前位置的最长无重复子串长度
len[i] = i - bPos + 1;
}
//跟新当前字符出现的位置
map.put(charArr[i], i);
}
}
//遍历len,最大值即为所求
int max = len[0];
for(int i: len) if(i > max) max = i;
return max;
}
}