详见:
Leetcode 3
问题分析
T3:
无重复最长子串问题:
问题描述:
小声吐槽:在题目中也是会有这样的字符串的qaq
解法1:滑动窗口
int lengthOfLongestSubstring(string s) {
if (s.length() == 1)//考虑length==1(实际上还是我懒)
return 1;
int count = 0;
for (int width = 0; width<s.length()+1; width++)//窗口长度
{
for (int start = 0; start+width<s.length()+1; start++)//起始位置
{
string sub = s.substr(start, width);//字串
if (IsThere(sub))
{
count=width;//满足条件使长度与窗口长度相同
break;//无须继续探索是否后面还有一样长的子串
}
}
//控制时间复杂,当
if(count<width)
return count;
}
return count;
}
};
解法2:哈希查找
这个有借鉴解答区大神,果然我和大神还是差不止一个天花板啊T_T
其实这个方法开始怎么也想不通(心灰意冷.jpg),后来在客厅喝了口水照了照镜子(歪歪歪)想到了——队列的方法。
如果像我解法一里用的滑动窗口的方法,实质上比蛮力法相当!只不过使用了小技巧没有超出时间限制!所以我考虑到了队列,即:
遍历原字符串;
如果队列中不含有该字符,则入列;
如果队列中含有该字符,则依次出列,直至队列中无该字符串,入列。
返回最大队列长度即可。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int Map[256]={0};//哈希存储
int left=0;//左值,即相当于front
int count=0;//最大值
for(int i=0;i<s.length();i++)
{
//判断条件:考虑该元素是否在队列中
if(Map[s[i]]==0||Map[s[i]]<left+1){
if(count<i-left+1){
//将此时的队列长度与最大值作比较
count=i-left+1;
}
}
else{
left=Map[s[i]];
}
Map[s[i]]=i+1;//Map的作用主要是便利过程中存储这个字母最后一次出现的地方,为什么+1呢?因为要和第一个区分开!
}
return count;
}
};
T30:最小覆盖字串
问题描述:
解法1:(这个解法未通过)
如果少一点这样的测试数据我的算法路程也许会很美好
思路:
这个就是典型的滑动窗口啦,如果没有vector在恐怕真的困难很多qaq直接上代码——
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> solution;//解集
//极端情况,主要是因为不这样做leetcode会说我执行错误(遇到十多次执行错误了唉)
if (s.length() == 0 || words.size() == 0)
{
return solution;
}
int len = words[0].length();//words中每个字符串的长度
int width = len * words.size();//窗口长度
sort(words.begin(), words.end());//将words提前排序
//滑动窗口
for (int i = 0; i + width<s.length() + 1; i++)
{
string sub = s.substr(i, width);//取得窗口长度的子串
vector<string> temp;
for (int j = 0; j<words.size(); j++)
{
temp.push_back(sub.substr(j*len, len));//将子串分为规定长度的字符串
}
sort(temp.begin(), temp.end());//排序
//与words里的字符串作比较
if (temp == words)
solution.push_back(i);
}
return solution;
}
};
解法2:(为了使其通过的改进版滑动窗口算法)
只可惜还不是很高效
这次滑动窗口的思路来源于分组式滑动。因为当窗口滑动起始位置到超过len长度的位置,后面比较的词语都是重复!因此,我们对算法进行了改进。
class Solution {
public:
vector<int> findSubstring(string s, vector<string>& words) {
vector<int> solution;
if (s.length() == 0 || words.size() == 0)
{
return solution;
}
int len = words[0].length();
int width = len * words.size();
int num = words.size();
sort(words.begin(), words.end());
for (int i = 0; i<len; i++)
{
vector<string> temp;
vector<string> temp1;
//从某一位置开始获得所有长度相等的字符串
for (int j = 0; (j+1)*len+ + i<=s.length(); j++)
{
temp.push_back(s.substr(i + j * len, len));
}
//滑动窗口,此时的窗口准确来说,是字符串个数
for (int j = 0; i+j*len+width<s.length()+1; j++) {
vector<string> temp1(temp.begin() + j, temp.begin() + j + num);
sort(temp1.begin(), temp1.end());
if (temp1 == words)
solution.push_back(i+j*len);
}
}
//去重
sort(solution.begin(), solution.end());
vector<int>::iterator iter = unique(solution.begin(), solution.end());
solution.erase(iter, solution.end());
return solution;
}
};
参考链接
https://blog.csdn.net/haiross/article/details/45746203
https://blog.csdn.net/sunshihua12829/article/details/50484966