滑动窗口法和暴力求解法的battle
力扣题号以及题目描述:
力扣题号
题号:3
题名:无重复字符的最长子串
难度:中等
题目表述
暴力求解的思路:
用i遍历s,再从s[i]开始,用j遍历剩余的字符串,将字符储存到哈希表里,当哈希表里出现重复的字符时跳出内层循环,根据hash表的size函数,得到哈希表的长度,保存此长度。当外层循环结束时,得到最大的长度值。
bug:
在力扣求解时,会超时,算法的时间复杂度O(N^2)。
代码如下:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int length = s.size();
vector<int> result(length,-1);
//unordered_map<int,char> table_hash;
unordered_map<char,int> table_hash;
for(int i = 0; i != s.size(); ++i){
for(int j = i; j != s.size(); ++j){
if(table_hash.find(s[j]) != table_hash.end()) break;
else table_hash[s[j]] = s[j] - '0';
}
result[i] = table_hash.size();
table_hash.clear();
}
return *max_element(result.begin(),result.end());
}
};
结果
滑动窗口法的思路
利用双指针的思想,第一个指针,在窗口的左边界,另一个指针,在窗口的右边界。首先移动右边界,判断是否满足不重复的条件,若是不满足,则移动窗口的左边界。在移动左边界之前需要计算两个指针的距离,这个值在求解过程中的最大值就是所需的答案。
注意事项
滑动窗口法的形式,是类似以下这种形式:
for(int i = 0 ; i < length; ++i){
while(xxxxx){
++j;
}
}
经过测试吧,i这个指针是滑动窗口的右边界比较好,因为一定会滑到头。
j这个指针,则为滑动窗口的左边界。
hashmap的理解
之前我使用 unordered_map<char,int>这个容器时,总喜欢将字符char 作为key,然后呢 将 char字符 - ‘0’ 字符 作为数字 存储到 value 里面。
实际上 对 value 这个值应用不够充分。可以将 value 存储成 字符出现的次数。
还有一个特殊的点是,hashmap里面没有存储的字符,当我们利用hashmap使用该字符时,它的value值默认是0。
代码如下:
class Solution {
public:
unordered_map<char,int> hash_table;
int lengthOfLongestSubstring(string s) {
int len = s.size();
int i,j=0;// 两个指针
int length = 0;
for(j = 0; j != len; ++j){
while(hash_table[s[j]] != 0){ //s[j] 出现过
--hash_table[s[i]];
++i;
}
length = max(length,j - i + 1);
++hash_table[s[j]];
}
return length;
}
};