题目描述:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
拿到题最先想到的,不,是不经思索地就是暴力求解。
bool ifRepeat(char* ss) {
for (int i = 0; i < strlen(ss) - 1; i++) {
for (int j = i + 1; j < strlen(ss); j++) {
if (ss[i] == ss[j]) return true;
}
}
return false;
}
int lengthOfLongestSubstring(string &s) {
int i, max_s = 1;
for (int k = 0; k < s.length() - 1; k++) {
for (i = k + 1; i < s.length(); i++) {
int len = i - k + 1;
char* ss = new char[len+1];
ss[len] = '\0';
for (int j = k; j <= i; j++)
ss[j - k] = s[j];
if (!ifRepeat(ss)) {
if (max_s < i - k + 1) max_s = i - k + 1;
}
delete[] ss;
}
}
return max_s;
}
粗略估算一下,时间复杂度为O(n^4),还要不停的分配内存,调用函数,又臭又长,写的时候还遇到了很多问题。提交,好家伙,超出时间限制。
于是寻找新的解题方法,想啊想,忽然想到了插入排序:将新的数据和已排好位置的序列比较,并插入到正确的位置。由此得到启发,对于该题,我将新的字符与当前无重复字符字串所有字符一一比较。这样就省去了大量的重复比较,还不用分配内存。
算法如下:
1.输入一个新的字符s[j];
2.将新的字符与已经比较好的无重复字符字串 s[i]~s[j-1] 中所有字符进行比较,k从 j-1 ~ i 进行遍历:
若与s[k]相等(此时 i<=k<j),则不再继续比较,执行3;
3.计算当前长度 j-k 并与最长长度比较,若大于,则替换之;
4.更新当前无重复字符子串为 s[k+1]~s[j],继续执行1。
代码:
int lengthOfLongestSubstring(string& s) {
int max = 0, len = 0;
if (s.length()) max = 1;
int i = 0, j = 1, k;
for (; j < s.length(); j++) {
k = j - 1;
while (k >= i) {
if (s[j] == s[k]) {
len = j - k;
break;
}
k--;
}
len = j - k;
if (len > max) max = len;
i = k + 1;
}
return max;
}
时间复杂度为O(n^2)。
不过依然有个问题,在我删掉第九行的len = j - k;后提交,运行时间反而比删除之前慢了,按理说少进行了数次运算,应该变快才是啊。