package
0.0.0-20230809123828-b071cee2968a
Repository: https://github.com/codehanhan/leetcode-go.git
Documentation: pkg.go.dev
# README
面试题 17.18.最短超串
1. 题目描述
假设你有两个数组,一个长一个短,短的元素均不相同。找到长数组中包含短数组所有的元素的最短子数组,其出现顺序无关紧要。
返回最短子数组的左端点和右端点,如有多个满足条件的子数组,返回左端点最小的一个。若不存在,返回空数组。
示例 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
标签
数组
哈希表
滑动窗口
2. 解题
- map<int, int> need:记录要完全覆盖small数组,滑动窗口内需要覆盖的数字及其对应的个数
- int diff:记录要完全覆盖small数组,滑动窗口内需要覆盖的数字总个数
- int l:指向窗口的左边界
- int r:指向窗口的右边界
- int minLen:表示满足条件的最短子数组长度
- 思路:
need是一个字典,用来存储要包含small数组中的所有元素还需要覆盖的各个数字的数量。diff记录需要覆盖的所有数字的总数,diff的增大与减小与need是同步的,但是diff必须大于等于0。
那么,当我们遍历big中的数字a时,如果数字a在small中出现,那么我们将need[a]减一,说明窗口内增加了一个a,需要a的数量减一;
注意:need[a]是可能为负数的,为负数说明当前窗口内的元素a超过了数组small中的元素a的数量
如果,数字a在small中未出现,说明该数字对是否包含small是完全没有影响的,不用执行任何操作;
然后,当访问数组big中的数字一直到某个位置时,need中的所有键对应的值都为0,diff也等于0,此时当前窗口已经包含了small数组里的所有元素,甚至多余。记录当前窗口的长度len,并将左指针l右移,寻找包含small数组的最大下标l(即最短区间)
我们只需要找到完整包含small数组的最短区间[l, r]即可。
2)步骤:
- 使用small数组初始化need,need存储small中的所有元素
- 使用左、右指针l和r遍历big数组
- 如果区间[l, r]内的元素未完全覆盖small(即diff != 0),r右移
- 如果区间[l, r]内的元素完全覆盖small(即diff == 0),l右移,压缩区间,直到区间[l, r]不完全覆盖small数组
- 重复步骤3-4,直到找到完全覆盖small数组的最短区间[l, r]