【剑指offer】【字符串】48. 最长不含重复字符的子字符串
题目链接:https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof/
双指针算法
i在前,j在后,分别指向不重复子串的头和尾;使用一个哈希表每个字符出现的次数,当遍历到j时,发现s[j]的个数大于1,那么就让i向前移动,直到s[j]的个数等于1;
每次都判断当前的不重复子串长度是不是最大的。
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> hash;
int res = 0;
for(int i = 0, j = 0; j < s.size(); j++)
{
//如果s[j]的个数大于1,清除前面重复的s[j]
if(++hash[s[j]] > 1)
{
//i往前移动,直到s[j]的个数==1
while(i < j)
{
hash[s[i]]--;
i++;
if(hash[s[j]] == 1) break;
}
}
//更新res
res = max(res, j- i + 1);
}
return res;
}
};
动态规划
状态表示: f[i] 表示以i结尾的字符串的不重复子串的最大长度;
状态计算:
- s[i] 未出现过,f[i] = f[i - 1] + 1;
- s[i] 出现过,记i到s[i]上一次出现的距离为d;分两种情况:
1). d <= f[i - 1], 那么f[i] = d;
2). d > f[i - 1], 那么f[i] = f[i - 1] + 1;
使用一个哈希表来记录,每个字符出现的位置;初始值都为-1;代表没有出现过;
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int curLen = 0, maxLen = 0;
// 记录,每个字符出现的位置
unordered_map<char, int> pos;
for(int i = 0; i < s.length(); ++i)
pos[s[i]] = -1;
for(int i = 0; i < s.length(); ++i)
{
////s[i]之前出现的位置
int prevINdex = pos[s[i]];
//s[i]之前未出现过 或者 d > f[i - 1]
if(prevINdex < 0 || i - prevINdex > curLen)
++curLen;
// d <= f[i - 1]
else
{
if(curLen > maxLen)
maxLen = curLen;
curLen = i - prevINdex;
}
pos[s[i]] = i;
}
if(curLen > maxLen)
maxLen = curLen;
return maxLen;
}
};
知识的价值不在于占有,而在于使用