1.题目详情
Given a string, find the length of the longest substring without repeating characters.
给出一个字符串,找到最长的且没有重复字符的子串。
Example 1:
Input: “abcabcbb”
Output: 3
Explanation: The answer is “abc”, with the length of 3.
Example 2:
Input: “bbbbb”
Output: 1
Explanation: The answer is “b”, with the length of 1.
Example 3:
Input: “pwwkew”
Output: 3
Explanation: The answer is “wke”, with the length of 3.
Note that the answer must be a substring, “pwke” is a subsequence and not a substring.
完善下面代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
}
};
2.解题方法
2.1 解法1
解法一类似于暴力破解:执行for循环,从每个字符开始,不断向后延伸,将扩展到的字符放入到一个数组中,遇到重复字符再停止,然后比较现有子串长度与记录下来的最大长度,选出最大长度。
优化:每个字符在C++中都对应一个数字,只要声明一个足够大的数组,将字符对应下标的元素标为1,就相当于将字符放入到数组了,而且不用遍历这个数组。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int start = 0, maxLength = 0, size = s.size();
while (start < size - maxLength) {
int chars[256] = {0};
int index = start;
int length = 0;
int now = (int)s[index];
while (chars[now] == 0 && index < size) {
index++;
chars[now] = 1;
length++;
now = (int)s[index];
}
if (length > maxLength)
maxLength = length;
start++;
}
return maxLength;
}
};
这里的时间花费为20ms。
2.2 解法2
解法二是对解法一的优化,因为从一个字符开始扩展延伸字符串,直到遇到一个重复在延伸的字符串中已有的字符,那么可以确定在开始字符到已有字符间的每个字符开始延伸的字符串都比不上现有的字符串,所以可以直接从已有字符的下一个字符重新开始延伸字符串。
如果将开始延伸字符串的字符认为是start,则start将不断的与重复字符替换,这也是延伸出来的子串的最左边。子串的右边则是不断的加1,向后延伸。
所以这里需要用两个数组,记录每个字符的位置与现有的重复字符。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int size = s.size();
int chars[256] = {0};
int locas[256] = {0};
int start = 0;
int maxLength = 0;
for (int i = 0; i < size; i++) {
int now = s[i];
start = max(start, (chars[now] ? (locas[now] + 1) : 0));
maxLength = max(maxLength, i - start + 1);
chars[now] = 1;
locas[now] = i;
}
return maxLength;
}
};