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


    题目链接

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

    题目描述

    假设你有两个数组,一个长一个短,短的元素均不相同(如果短的元素可以相同,则本题与lc76题目一样)。找到长数组中包含短数组所有的元素的最短子数组,其出现顺序无关紧要。

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

    示例 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缩小窗口,直到不满足要求(注意是逐渐增加left缩小窗口,而不能和自己想的滑动窗口那样,强行对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 };
  • 相关阅读:
    plsql调试存储过程卡住的原因以及处理
    JavaWeb三大组件(Servlet、Filter、Listener)的区别
    单点登录原理
    Oracle 导表异常处理方案 (解决空表导出出错问题)
    在Oracle中删除用户时提示:ORACLE无法删除当前连接用户
    VisualSvn的权限管理
    MySql常用命令总结
    Oracle 常用SQL
    参数
    java
  • 原文地址:https://www.cnblogs.com/XDU-Lakers/p/12922749.html
Copyright © 2020-2023  润新知