关键知识
字符串处理和识别
简单介绍
字符串内的字符特点,可以通过两层遍历来实现。这样代码逻辑清晰易懂,但是时间效率比较差。另外一种,就是构建128个字符串标志符, 在上面记录字符串的特征。但是逻辑有点难,需要明天继续理解。
解题过程
两层遍历
在第一次遍历的基础上,记录该段长度的起始位置,不断加入新的字符进来,如果新加入的字符在前面这段字符内存在相同的字符,则计算并记录该段长度。在相同的旧字符后面一个开始重新计算一个字符段。在每次计算段长的过程中不断更新字符段的最大长度。
时间复杂度: O(n*最大长度)
空间复杂度: O(1)
单层遍历
用一个128的bool数组记录字符,在遍历的过程中,将两层中的第二层改成一个长度为128的bool数组,在第一层遍历的时候,不断判断当前段是否存在这个字符,如果存在则计算当前段的最大长度,然后将旧字符和该字符前的所有字符记为false,从旧字符的后面开始重新开始新的一段。在判断字符长度的时候不断更新最大段长度,最后还要计算最后一段长度并更新最大段长度。优点就是只用长度为128的bool数组就可以减少一层的遍历,大大降低时间复杂度。
时间复杂度: O(n)
空间复杂度: O(128)
题目
个人解答
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int pos = 0, t, l = 0, max = 0;
int n = s.length();
if (n == 0) return 0;
else if (n == 1) return 1;
for (int i = 1; i < n; i++) {
t = find(s, pos, i-1, s[i]);
if (t != -1) {
l = i - pos;
max = max > l ? max : l;
pos = t + 1;
}
}
l = n-pos;
max = max > l ? max : l;
return max;
}
int find(string s, int front, int rear, int tar) {
if (front > rear) return -1;
for (int i = front; i <= rear; i++) {
if (s[i] == tar) return i;
}
return -1;
}
};
学习方法
class Solution {
public:
int lengthOfLongestSubstring(string s) {
auto seen = vector<bool>(128, false);
int i = 0, j = 0;
int len = 0;
while (j < s.length()) {
if (seen[s[j]]) {
len = max(len, j - i); //判断不重复的段长度
while (s[i] != s[j]) {
seen[s[i]] = false;
++i;
}
++i;
} else {
seen[s[j]] = true;
}
++j;
}
len = max(len, j - i); //最后一段
return len;
}
};