题目:LeetCode 3. 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.
解题思路:
维护一个256的数组(因为ASCII是0~255)记录当前字符上一次出现的位置p。一个int记录字串的起点s。当前字符的位置i。当前最长字串max
遍历字符串:
当s<p<i时(注意:下标为p和i的字符相同),起点往后挪s=p,更新字符位置p=i,保留i-start与max中的较大值。
当p<s<i时,保留i-start与max中的较大值。
注意空字符串和一个字符串等临界条件。
时间复杂度O(n),空间复杂度O(1)。
代码:
int lengthOfLongestSubstring(string s) {
int maxLengthOfSub = 0;
int startIdx = -1;
int charIndex[256] = {0};
memset(charIndex, -1, 256*4);
for (int i = 0; i < s.length(); i++)
{
if (charIndex[s[i]] > startIdx)
startIdx = charIndex[s[i]];
maxLengthOfSub = maxLengthOfSub > i - startIdx ? maxLengthOfSub : i - startIdx;
charIndex[s[i]] = i;
}
return maxLengthOfSub;
}
我的解题过程:
刚开始想到的是模式匹配和kmp算法,于是按着kmp算法思路写了一份:
想法:起点start,与输入同等规模的数组p,存放到当前位置的子串长度,当前下标i。遍历字符串,每次字串长度+1,然后再遍历start到i,若下标k(start<k<i)和下标i的字符相同,移动start=k,减去start之前的部分,p[k+1]~p[i] 减去p[k]。
时间复杂度O(),空间复杂度O(n)。
int lengthOfLongestSubstring(string s) {
int l = s.length();
if (l == 0)return 0;
int lengthOfSub = 1;
int startIdx = 0;
int *p = new int[l];
p[0] = 1;
int cut;
for (int i = 1; i < l; i++)
{
p[i] = p[i - 1] + 1;
cut = 0;
for (int j = startIdx; j < i; j++)
{
p[j] -= cut;
if (s[i] == s[j])
{
startIdx = j + 1;
cut+= p[j];
}
}
p[i] -= cut;
if (p[i] > lengthOfSub)
lengthOfSub = p[i];
}
return lengthOfSub;
}
最后test六百多的时候报了整形数组越界。因为输入数据过大p[i] -= cut;没有考虑到减成负数,一直减到把int爆了。
题目没有给定输入规模大小。猜想这题可能不用管大小,于是想到了ASCII是固定的256个。便有了最上面的题解。