LeetCode面试题17.18 最短超串(典型滑动窗口)

Posted xdu-lakers

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode面试题17.18 最短超串(典型滑动窗口)相关的知识,希望对你有一定的参考价值。

题目链接

https://leetcode-cn.com/problems/shortest-supersequence-lcci/

题目描述

假设你有两个数组,一个长一个短,短的元素均不相同。找到长数组中包含短数组所有的元素的最短子数组,其出现顺序无关紧要。

返回最短子数组的左端点和右端点,如有多个满足条件的子数组,返回左端点最小的一个。若不存在,返回空数组。

示例 1:
输入:
big = [7,5,9,0,2,1,3,5,7,9,1,1,5,8,8,9,7]
small = [1,5,9]
输出: [7,10]

示例 2:
输入:
big = [1,2,3]
small = [4]
输出: []

提示:
big.length <= 100000
1 <= small.length <= 100000

解题思路

1.典型利用滑动窗口

定义滑动窗口为[left,right],当滑动窗口内的元素满足small数组,则把left与right的值都设置为从left下标开始第二次出现small数组中的元素的下标。例如big数组[1,2,3,5,7,6],small数组[1,3,5],当left = 0,right = 3时,滑动窗口满足small元素,则把left与right值设置为2。然后继续重复以上操作。自己想的滑动窗口最终因为超时没能AC,但是所有用例都通过了。

标准的滑动窗口:

1.把[left,right]称为一个窗口;
2.先右移右指针扩大窗口,直到窗口中的数字满足small数组要求;
3.满足要求时,停止增加right,转而增加left缩小窗口,直到不满足要求
4.重复2,3步直到right走到big尽头

滑动窗口的模板:

int left = 0, right = 0; //left right为双指针

while (right < s.size())

{

    window.add(s[right]);

    right++; //右移右指针扩大窗口

    while (valid) //直到窗口中的数字满足small数组要求;

    {

        window.remove(s[left]); //满足要求时,停止增加right,转而增加left缩小窗口,直到不满足要求

        left++;

    }

}

AC代码

 1 class Solution {
 2 public:
 3     vector<int> shortestSeq(vector<int>& big, vector<int>& small) {
 4         vector<int> ans;
 5         if(small.size()>big.size()) return ans;
 6         map<int,int>b_mp;
 7         map<int,int>s_mp;
 8         for(int i = 0; i < small.size(); i++) s_mp[small[i]]++;
 9         int count = 0;
10         int l = 0;
11         int r = 0;
12         int l_ans=-1;
13         int r_ans=-1;
14         int max = INT_MAX;
15         while(l <= r && r < big.size())
16         {
17             if(s_mp[big[r]] == 0) //右指针右移,扩大窗口
18             {
19                 r++;
20                 continue;
21             }
22             else
23             {
24                 b_mp[big[r]]++;
25                 if(b_mp[big[r]] == 1) count++;
26             }
27             
28             if(count == small.size()//valid条件) //整个if语句对应模板中 window.remove(s[left]);【开始缩小滑动窗口->对l的值进行处理】
29             {
30                 while(l <= r)
31                 {
32                     if(b_mp[big[l]] == 0) l++;
33                     else if(b_mp[big[l]] == 1) break;
34                     else if(b_mp[big[l]] > 1) //本句代码是为了处理如下例子:big数组[1,2,1,3,5,7,6],small数组[1,3,5]
35                     {
36                         b_mp[big[l]]--;
37                         l++;
38                     }
39                 }
40                 int len = r - l;
41                 if(len < max) //迭代更新len值
42                 {
43                     max = len;
44                     l_ans = l;
45                     r_ans = r;
46                 }
47             }  
48             r++;
49         }
50         if(max != INT_MAX)
51         {
52             ans.push_back(l_ans);
53             ans.push_back(r_ans);
54         }
55 
56         return ans;
57     }
58 };

 

以上是关于LeetCode面试题17.18 最短超串(典型滑动窗口)的主要内容,如果未能解决你的问题,请参考以下文章

17.18. 最短超串

每日一题剑指 Offer II 115. 重建序列

Leetcode刷题100天—面试题 16.16. 部分排序(排序)—day58

Leetcode刷题100天—面试题 16.16. 部分排序(排序)—day58

从一道算法面试题看我国信息科技的原创性不足:查找包含所有元素的最短子数组

算法千题案例每日LeetCode打卡——92.最短补全词