面试题 17.18. 最短超串
假设你有两个数组,一个长一个短,短的元素均不相同。找到长数组中包含短数组所有的元素的最短子数组,其出现顺序无关紧要。
返回最短子数组的左端点和右端点,如有多个满足条件的子数组,返回左端点最小的一个。若不存在,返回空数组。
示例 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]
输出: []
代码如下:
class Solution {
public int[] shortestSeq(int[] big, int[] small) {
//左右双指针表示滑动窗口,start和min用来保存最优解
int left = 0;
int right = 0;
int start = 0;
int count = 0; //count用来保存匹配的个数
int min = Integer.MAX_VALUE;
HashMap<Integer,Integer> window = new HashMap<>();
HashMap<Integer,Integer> map = new HashMap<>();
for(int x : small) {
map.put(x,map.getOrDefault(x,0) +1);
}
//移动right扩大窗口
while (right < big.length) {
int a = big[right];
if (map.containsKey(a)) {
window.put(a,window.getOrDefault(a,0) +1);
if (window.get(a) == map.get(a)) {
count++;
}
}
right++;
//直到满足的时候 要开始缩小左边
while (count == map.size()) {
//更新最小窗口
if ((right - left) < min) {
start = left;
min = right -left;
}
int b = big[left];
if (map.containsKey(b)) {
window.put(b,window.getOrDefault(b,0) -1);
if (window.get(b) < map.get(b)) {
count--;
}
}
left++;
}
}
//判断min有没有发生改变,改变了说明有符合的情况,如果没有直接返回一个[]
if (min == Integer.MAX_VALUE) {
return new int[0];
}
return new int[]{start,min+start-1};
}
}