题目
算法思路及代码实现
方法一:暴力法
假设我们有一个函数 bool allUnique(string substring) ,如果子字符串中的字符都是唯一的,它会返回true,否则会返回false。 我们可以遍历给定字符串 s 的所有可能的子字符串并调用函数 allUnique。 如果事实证明返回值为true,那么我们将会更新无重复字符子串的最大长度的答案。
为了枚举给定字符串的所有子字符串,我们需要枚举它们开始和结束的索引。假设开始和结束的索引分别为 ii 和 j。那么我们有 0≤i<j≤n (这里的结束索引 j 是按惯例排除的)。因此,使用 ii 从0到 n - 1以及 j 从 i+1到 n 这两个嵌套的循环,我们可以枚举出 s 的所有子字符串。
#include <iostream>
#include <string>
#include <map>
using namespace std;
class Solution{
public:
int lengthOfLongestSubstring(string s){
int ans = 0;
//遍历所有无重复字符的子串
for(int i = 0; i<s.size(); i++)
for(int j=i+1; j<=s.size(); j++){
if(allUnique(s,i,j))
ans = max(ans,j-i); //保存最长子串的长度
}
return ans;
}
bool allUnique(string s, int begin, int end){
map<char,int> hash;
for(int i=begin; i<end; i++){
if(hash.find(s[i])!=hash.end())
return false; //存在重复字符则返回false
hash[s[i]]=i;
}
return true;
}
};
int main()
{
Solution longstring;
string s1 = "pwwkew";
cout << longstring.lengthOfLongestSubstring(s1) << endl;
//system("pause");
return 0;
}
方法二:滑动窗口
#include <iostream>
#include <string>
#include <unordered_set>
using namespace std;
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// 哈希集合,记录每个字符是否出现过
unordered_set<char> occ;
int n = s.size();
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
int rk = -1, ans = 0;
// 枚举左指针的位置,初始值隐性地表示为 -1
for (int i = 0; i < n; ++i) {
if (i != 0) {
// 左指针向右移动一格,移除一个字符
occ.erase(s[i - 1]);
}
while (rk + 1 < n && !occ.count(s[rk + 1])) {
// 不断地移动右指针
occ.insert(s[rk + 1]);
++rk;
}
// 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = max(ans, rk - i + 1);
}
return ans;
}
};
int main()
{
Solution longstring;
string s1 = "pwwkew";
cout << longstring.lengthOfLongestSubstring(s1) << endl;
//system("pause");
return 0;
}
小记
1) unordered_set的介绍
1、无序集是一种容器,它以不特定的顺序存储惟一的元素,并允许根据元素的值快速检索单个元素。
2、在unordered_set中,元素的值同时是唯一标识它的键。键是不可变的,只可增删,不可修改
3、在内部,unordered_set中的元素没有按照任何特定的顺序排序,而是根据它们的散列值组织成桶,从而允许通过它们的值直接快速访问单个元素(平均时间复杂度为常数)。
4、unordered_set容器比set容器更快地通过它们的键访问单个元素,尽管它们在元素子集的范围迭代中通常效率较低。
5、容器中的迭代器至少是前向迭代器。
2)unordered_set的count
此函数接受单个参数element 。表示容器中是否存在需要检查的元素。
如果元素存在于容器中,则此函数返回1,否则返回0。
示例:
#include<cstdio>
#include<iostream>
#include<unordered_set>
using namespace std;
int main(){
unordered_set<int> us;
us.insert(1);
us.insert(2);
us.insert(3);
cout<<us.count(3)<<endl;//存在,返回1
cout<<us.count(6)<<endl;//不存在,返回0
return 0;
}