【leetcode】滑动窗口问题

详见:
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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值