蓝雨原创,转载请注明出处。contact author: qinglanyu_jun@foxmail.com
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.
Solution 1 滑动窗口法
窗口左指针 i i i,右指针 j = i + 1 j=i+1 j=i+1;右指针依次从字符串左侧到最右侧滑动。只要指针j指向的字符在窗口内 ( k ) (k) (k),则移动左指针到重复元素 k k k的右侧 ( k + 1 ) (k+1) (k+1);否则移动右指针,增加窗口长度。窗口右指针滑动至字符串最右侧时,经过的最大窗口宽度即为最大不重复子串的长度。
code
class Solution {
#define MAX(a, b) ((a)>(b)?(a):(b))
public:
int lengthOfLongestSubstring(string s) {
int m = 0;
if (s.length() == 0) return m;
if (s.length() > 0) m = 1;
for (unsigned i = 0, j = i + 1; j < s.length(); ++j) {
unsigned k = i; //--------------
for (; k < j; ++k) { //
if (s[k] == s[j]) { // 此处判断是否重复出现可以再优化
i = k + 1; //
break; //
} //---------------
}
if (k == j) {
m = MAX(m, j - i + 1);
}
}
return m;
}
};
该方法不需要额外的存储空间,复杂度为 O ( 1 ) O(1) O(1),时间复杂度为 O ( n 2 ) O(n^{2}) O(n2)。
执行结果:通过
执行用时: 8ms,在所有C++提交中击败了94.40%的用户
内存消耗: 7MB,在所有C++提交中击败了100.00%的用户
Solution 2 滑动窗口法+桶(数组)优化
在上面的方案1中,判断原子串的元素 s [ j ] s[j] s[j]是否已经出现在子串中时,每次都遍历完整个子串 s [ i , j ) s[i, j) s[i,j),显然在时间上还可以优化。此处添加一个有限元素的数组 s u b sub sub来临时存储出现过的字符。即是一种以空间换时间的方案。
code
class Solution {
#define MAX(a, b) ((a)>(b)?(a):(b))
public:
int lengthOfLongestSubstring(string s) {
// s[i, j) is the window
int m = 0, len = 0;
vector<int> sub(128, -1); // for 128 characters
for (int i = 0, j = 0; j < s.length(); ++j)
{
// when s[j] belongs to s[i, j)
if (sub[s[j]] >= i)
{
i = sub[s[j]] + 1;
len = j - i;
}
sub[s[j]] = j;
len++;
m = MAX(m, len);
}
return m;
}
};
该方法只需遍历一遍原字符串,需要一个定长的数组来存储所有可能出现的字符,空间复杂度为 O ( Σ ) O(\Sigma) O(Σ),其中 Σ \Sigma Σ为可能出现的字符数,时间复杂度为 O ( n ) O(n) O(n)。
执行结果:通过
执行用时: 8ms,在所有C++提交中击败了94.53%的用户
内存消耗: 7.7MB,在所有C++提交中击败了100.00%的用户