题目描述:中等
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
这道题思考两种方法:
法一:用滑动窗口
class Solution {
public int lengthOfLongestSubstring(String s) {
// 设置左右两个指针表示滑动窗口
int left = 0;
int maxLength = 0;
for (int i = 0; i < s.length(); i++) {
// 滑动窗口的右指针是当前下标+1
int right = i + 1;
String subStringLeft = s.substring(left, i);
String currentChar = s.substring(i, i + 1);
// 如果滑动窗口内有重复元素就更新右坐标
while (subStringLeft.contains(currentChar)) {
//contain函数,如果值参数出现在此字符串内,或者值为空字符串(“”),则为true; 否则为false
left++;
subStringLeft = s.substring(left, i);
}
String subString = s.substring(left, right);
maxLength = Math.max(maxLength, subString.length());
}
return maxLength;
}
}
滑动窗口提交结果:
用时18豪秒
法二:
class Solution {
public int lengthOfLongestSubstring(String s) {
// 记录字符上一次出现的位置
int[] last = new int[128];
for(int i = 0; i < 128; i++) {
last[i] = -1;
}
int n = s.length();
int res = 0;
int start = 0; // 窗口开始位置
for(int i = 0; i < n; i++) {
int index = s.charAt(i);
start = Math.max(start, last[index] + 1);
res = Math.max(res, i - start + 1);
last[index] = i;
}
return res;
}
}
法二用时2毫秒
法三:(用时9ms)
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s.length()==0) return 0;
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;//最长子串长度
int left = 0;//滑动窗口左下标,i相当于滑动窗口右下标
for(int i = 0; i < s.length(); i ++){
if(map.containsKey(s.charAt(i))){//charAt() 方法用于返回指定索引处的字符。索引范围为从 0 到 length() - 1。
left = Math.max(left,map.get(s.charAt(i)) + 1); //map.get():返回字符所对应的索引,当发现重复元素时,窗口左指针右移
} //map.get('a')=0,因为map中只有第一个a的下标,然后更新left指针到原来left的的下一位
map.put(s.charAt(i),i); //再更新map中a映射的下标
max = Math.max(max,i-left+1); //比较两个参数的大小
}
return max;
}
}
法四:
遍历字符串,并将遍历到的字符串和之前的字符作为一个临时字串,如果遍历到的新的字符被包含在这个临时字串中,说明跟前面的重复了,那么就丢掉临时字串中重复字符及其左边的部分。如示例中,当遍历到 第二个‘a’时,与第一个字符也就是’a’重复,那么丢掉’a’,并加上新加入的’a’,此时临时串为 “bca”,长度为3,继续往后,遍历到’b’,丢掉第一个’b’,加入新的’b’,临时字串变成cab,长度依然为3,记录过程中的最大长度即可,如此直到结束。时间复杂度为0(n).
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s==null||s.length()<1)return 0;
String tempfLongsetSubString = s.charAt(0)+""; //
String lastRembered = tempfLongsetSubString;
for(int i = 1 ; i < s.length();i++){
char a = s.charAt(i);
int beginIndex = tempfLongsetSubString.indexOf(a);
if(beginIndex>-1) {
tempfLongsetSubString = tempfLongsetSubString.substring(beginIndex+1);
}
tempfLongsetSubString+=a;
if(tempfLongsetSubString.length()>lastRembered.length()) {
lastRembered = tempfLongsetSubString;
}
}
return lastRembered.length();
}
}