题目:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
来源:力扣(LeetCode)
重点:
哈希表、滑块
代码
时间复杂度o(n2)的方法:
class Solution {
public int lengthOfLongestSubstring(String s) {
String maxStr;
int maxLen=0,exchang_1;
int len=1,startIndex=0,endIndex=1;
if(s.length()==1)
return 1;
while(endIndex<=s.length()){
if(ifRepeat(s.substring(startIndex,endIndex))==100){//如果不重复
if(s.substring(startIndex,endIndex).length()>maxLen){ //如果目前滑块的长度比最长的记录长则替换
maxStr=s.substring(startIndex,endIndex);
maxLen=s.substring(startIndex,endIndex).length();
}
endIndex++;
}
else{//如果有重复则把滑块开始坐标移动到第一个重复字符的下一个位置,保持滑块长度不变的前提下右移尾坐标
System.out.println("此时startIndex="+startIndex+" endIndex="+endIndex);
//窗口滑动
exchang_1=startIndex;
startIndex=startIndex+ifRepeat(s.substring(startIndex,endIndex))+1;
endIndex=endIndex+ifRepeat(s.substring(exchang_1,endIndex))+1;
System.out.println("滑动后startIndex="+startIndex+" endIndex="+endIndex);
}
}
return maxLen;
}
//判断是否有字符重复
public int ifRepeat(String s){
Map<Character,Integer> m1=new HashMap();
for(int i=0;i<s.length();i++){
if(m1.containsKey(s.charAt(i)))
return m1.get(s.charAt(i));//有重复并输出重复的字符的第一次出现位置
else
m1.put(s.charAt(i),i);
}
return 100;//表示无重复
}
}
时间复杂度o(n)的方法:
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character,Integer> m1=new HashMap(); //哈希表存放当前子串中的每个字符和其相当位置
int starIndex=0,endIndex=0,maxLen=0,len=0; //滑块头坐标、尾坐标、最大滑块长度、当前滑块长度
while(endIndex<s.length()){ //当滑块尾坐标在字符串长度范围内则循环
if(m1.containsKey(s.charAt(endIndex)) && m1.get(s.charAt(endIndex))>=starIndex){ //易错点
starIndex=m1.get(s.charAt(endIndex))+1; //找到原子串重复字符的位置,把其下一个位置的坐标作为滑块首坐标
m1.put(s.charAt(endIndex),endIndex++); //把当前重复字符修改成最新的坐标值
}
else{ //如果新的字符在原字符串里没有,或者有但是在滑块首坐标之前,则把这个字符添加进滑块
m1.put(s.charAt(endIndex),endIndex++);
len=endIndex-starIndex; //首位坐标差及时当前子串长度
}
maxLen=len>maxLen?len:maxLen; //一旦当前子串长度比maxLen大则修改
}
return maxLen;
}
}