diff --git a/lcci/17.18.Shortest Supersequence/README.md b/lcci/17.18.Shortest Supersequence/README.md index fccd497f145e4..624705166151e 100644 --- a/lcci/17.18.Shortest Supersequence/README.md +++ b/lcci/17.18.Shortest Supersequence/README.md @@ -5,6 +5,7 @@ ## 题目描述 +

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

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

示例 1:

@@ -26,6 +27,15 @@ small = [4] ## 解法 + +**方法一:哈希表 + 双指针** + +我们定义两个哈希表,其中哈希表 $need$ 用于存储数组 $small$ 中的元素及其出现次数,哈希表 $window$ 用于存储当前滑动窗口中的元素及其出现次数。另外,我们用变量 $cnt$ 记录当前未满足条件的元素个数,用变量 $mi$ 记录最短子数组的长度,用变量 $k$ 记录最短子数组的左端点。 + +我们用双指针 $j$ 和 $i$ 分别表示滑动窗口的左右端点,初始时,$j$ 和 $i$ 均指向数组 $big$ 的第一个元素。我们先移动右指针 $i$,将 $big[i]$ 加入到 $window$ 中,如果 $window[big[i]]$ 的值小于等于 $need[big[i]]$ 的值,说明当前滑动窗口中包含数组 $small$ 中的一个元素,令 $cnt$ 减一。当 $cnt$ 的值等于 $0$ 时,说明当前滑动窗口中包含数组 $small$ 中的所有元素,此时我们移动左指针 $j$,将 $big[j]$ 从 $window$ 中减去,如果 $window[big[j]]$ 的值小于 $need[big[j]]$ 的值,说明当前滑动窗口不再包含数组 $small$ 中的所有元素,令 $cnt$ 加一。在滑动窗口移动的过程中,我们更新 $mi$ 和 $k$ 的值。 + +时间复杂度 $O(m + n)$,空间复杂度 $O(m + n)$。其中 $m$ 和 $n$ 分别是数组 $big$ 和 $small$ 的长度。 + ### **Python3** @@ -33,7 +43,24 @@ small = [4] ```python - +class Solution: + def shortestSeq(self, big: List[int], small: List[int]) -> List[int]: + need = Counter(small) + window = Counter() + cnt, j, k, mi = len(small), 0, -1, inf + for i, x in enumerate(big): + window[x] += 1 + if need[x] >= window[x]: + cnt -= 1 + while cnt == 0: + if i - j + 1 < mi: + mi = i - j + 1 + k = j + if need[big[j]] >= window[big[j]]: + cnt += 1 + window[big[j]] -= 1 + j += 1 + return [] if k < 0 else [k, k + mi - 1] ``` ### **Java** @@ -41,7 +68,139 @@ small = [4] ```java +class Solution { + public int[] shortestSeq(int[] big, int[] small) { + int cnt = small.length; + Map need = new HashMap<>(cnt); + Map window = new HashMap<>(cnt); + for (int x : small) { + need.put(x, 1); + } + int k = -1, mi = 1 << 30; + for (int i = 0, j = 0; i < big.length; ++i) { + window.merge(big[i], 1, Integer::sum); + if (need.getOrDefault(big[i], 0) >= window.get(big[i])) { + --cnt; + } + while (cnt == 0) { + if (i - j + 1 < mi) { + mi = i - j + 1; + k = j; + } + if (need.getOrDefault(big[j], 0) >= window.get(big[j])) { + ++cnt; + } + window.merge(big[j++], -1, Integer::sum); + } + } + return k < 0 ? new int[0] : new int[] {k, k + mi - 1}; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + vector shortestSeq(vector& big, vector& small) { + int cnt = small.size(); + unordered_map need; + unordered_map window; + for (int x : small) { + need[x] = 1; + } + int k = -1, mi = 1 << 30; + for (int i = 0, j = 0; i < big.size(); ++i) { + window[big[i]]++; + if (need[big[i]] >= window[big[i]]) { + --cnt; + } + while (cnt == 0) { + if (i - j + 1 < mi) { + mi = i - j + 1; + k = j; + } + if (need[big[j]] >= window[big[j]]) { + ++cnt; + } + window[big[j++]]--; + } + } + if (k < 0) { + return {}; + } + return {k, k + mi - 1}; + } +}; +``` + +### **Go** + +```go +func shortestSeq(big []int, small []int) []int { + cnt := len(small) + need := map[int]int{} + window := map[int]int{} + for _, x := range small { + need[x] = 1 + } + j, k, mi := 0, -1, 1<<30 + for i, x := range big { + window[x]++ + if need[x] >= window[x] { + cnt-- + } + for cnt == 0 { + if t := i - j + 1; t < mi { + mi = t + k = j + } + if need[big[j]] >= window[big[j]] { + cnt++ + } + window[big[j]]-- + j++ + } + } + if k < 0 { + return []int{} + } + return []int{k, k + mi - 1} +} +``` +### **TypeScript** + +```ts +function shortestSeq(big: number[], small: number[]): number[] { + let cnt = small.length; + const need: Map = new Map(); + const window: Map = new Map(); + for (const x of small) { + need.set(x, 1); + } + let k = -1; + let mi = 1 << 30; + for (let i = 0, j = 0; i < big.length; ++i) { + window.set(big[i], (window.get(big[i]) ?? 0) + 1); + if ((need.get(big[i]) ?? 0) >= window.get(big[i])!) { + --cnt; + } + while (cnt === 0) { + if (i - j + 1 < mi) { + mi = i - j + 1; + k = j; + } + if ((need.get(big[j]) ?? 0) >= window.get(big[j])!) { + ++cnt; + } + window.set(big[j], window.get(big[j])! - 1); + ++j; + } + } + return k < 0 ? [] : [k, k + mi - 1]; +} ``` ### **...** diff --git a/lcci/17.18.Shortest Supersequence/README_EN.md b/lcci/17.18.Shortest Supersequence/README_EN.md index c103b7134b247..f266c9c473a2e 100644 --- a/lcci/17.18.Shortest Supersequence/README_EN.md +++ b/lcci/17.18.Shortest Supersequence/README_EN.md @@ -41,13 +41,162 @@ small = [4] ### **Python3** ```python - +class Solution: + def shortestSeq(self, big: List[int], small: List[int]) -> List[int]: + need = Counter(small) + window = Counter() + cnt, j, k, mi = len(small), 0, -1, inf + for i, x in enumerate(big): + window[x] += 1 + if need[x] >= window[x]: + cnt -= 1 + while cnt == 0: + if i - j + 1 < mi: + mi = i - j + 1 + k = j + if need[big[j]] >= window[big[j]]: + cnt += 1 + window[big[j]] -= 1 + j += 1 + return [] if k < 0 else [k, k + mi - 1] ``` ### **Java** ```java +class Solution { + public int[] shortestSeq(int[] big, int[] small) { + int cnt = small.length; + Map need = new HashMap<>(cnt); + Map window = new HashMap<>(cnt); + for (int x : small) { + need.put(x, 1); + } + int k = -1, mi = 1 << 30; + for (int i = 0, j = 0; i < big.length; ++i) { + window.merge(big[i], 1, Integer::sum); + if (need.getOrDefault(big[i], 0) >= window.get(big[i])) { + --cnt; + } + while (cnt == 0) { + if (i - j + 1 < mi) { + mi = i - j + 1; + k = j; + } + if (need.getOrDefault(big[j], 0) >= window.get(big[j])) { + ++cnt; + } + window.merge(big[j++], -1, Integer::sum); + } + } + return k < 0 ? new int[0] : new int[] {k, k + mi - 1}; + } +} +``` + +### **C++** + +```cpp +class Solution { +public: + vector shortestSeq(vector& big, vector& small) { + int cnt = small.size(); + unordered_map need; + unordered_map window; + for (int x : small) { + need[x] = 1; + } + int k = -1, mi = 1 << 30; + for (int i = 0, j = 0; i < big.size(); ++i) { + window[big[i]]++; + if (need[big[i]] >= window[big[i]]) { + --cnt; + } + while (cnt == 0) { + if (i - j + 1 < mi) { + mi = i - j + 1; + k = j; + } + if (need[big[j]] >= window[big[j]]) { + ++cnt; + } + window[big[j++]]--; + } + } + if (k < 0) { + return {}; + } + return {k, k + mi - 1}; + } +}; +``` + +### **Go** + +```go +func shortestSeq(big []int, small []int) []int { + cnt := len(small) + need := map[int]int{} + window := map[int]int{} + for _, x := range small { + need[x] = 1 + } + j, k, mi := 0, -1, 1<<30 + for i, x := range big { + window[x]++ + if need[x] >= window[x] { + cnt-- + } + for cnt == 0 { + if t := i - j + 1; t < mi { + mi = t + k = j + } + if need[big[j]] >= window[big[j]] { + cnt++ + } + window[big[j]]-- + j++ + } + } + if k < 0 { + return []int{} + } + return []int{k, k + mi - 1} +} +``` +### **TypeScript** + +```ts +function shortestSeq(big: number[], small: number[]): number[] { + let cnt = small.length; + const need: Map = new Map(); + const window: Map = new Map(); + for (const x of small) { + need.set(x, 1); + } + let k = -1; + let mi = 1 << 30; + for (let i = 0, j = 0; i < big.length; ++i) { + window.set(big[i], (window.get(big[i]) ?? 0) + 1); + if ((need.get(big[i]) ?? 0) >= window.get(big[i])!) { + --cnt; + } + while (cnt === 0) { + if (i - j + 1 < mi) { + mi = i - j + 1; + k = j; + } + if ((need.get(big[j]) ?? 0) >= window.get(big[j])!) { + ++cnt; + } + window.set(big[j], window.get(big[j])! - 1); + ++j; + } + } + return k < 0 ? [] : [k, k + mi - 1]; +} ``` ### **...** diff --git a/lcci/17.18.Shortest Supersequence/Solution.cpp b/lcci/17.18.Shortest Supersequence/Solution.cpp new file mode 100644 index 0000000000000..0232b0e96176d --- /dev/null +++ b/lcci/17.18.Shortest Supersequence/Solution.cpp @@ -0,0 +1,32 @@ +class Solution { +public: + vector shortestSeq(vector& big, vector& small) { + int cnt = small.size(); + unordered_map need; + unordered_map window; + for (int x : small) { + need[x] = 1; + } + int k = -1, mi = 1 << 30; + for (int i = 0, j = 0; i < big.size(); ++i) { + window[big[i]]++; + if (need[big[i]] >= window[big[i]]) { + --cnt; + } + while (cnt == 0) { + if (i - j + 1 < mi) { + mi = i - j + 1; + k = j; + } + if (need[big[j]] >= window[big[j]]) { + ++cnt; + } + window[big[j++]]--; + } + } + if (k < 0) { + return {}; + } + return {k, k + mi - 1}; + } +}; \ No newline at end of file diff --git a/lcci/17.18.Shortest Supersequence/Solution.go b/lcci/17.18.Shortest Supersequence/Solution.go new file mode 100644 index 0000000000000..e5749e43573dd --- /dev/null +++ b/lcci/17.18.Shortest Supersequence/Solution.go @@ -0,0 +1,30 @@ +func shortestSeq(big []int, small []int) []int { + cnt := len(small) + need := map[int]int{} + window := map[int]int{} + for _, x := range small { + need[x] = 1 + } + j, k, mi := 0, -1, 1<<30 + for i, x := range big { + window[x]++ + if need[x] >= window[x] { + cnt-- + } + for cnt == 0 { + if t := i - j + 1; t < mi { + mi = t + k = j + } + if need[big[j]] >= window[big[j]] { + cnt++ + } + window[big[j]]-- + j++ + } + } + if k < 0 { + return []int{} + } + return []int{k, k + mi - 1} +} \ No newline at end of file diff --git a/lcci/17.18.Shortest Supersequence/Solution.java b/lcci/17.18.Shortest Supersequence/Solution.java new file mode 100644 index 0000000000000..59049a887c7e1 --- /dev/null +++ b/lcci/17.18.Shortest Supersequence/Solution.java @@ -0,0 +1,28 @@ +class Solution { + public int[] shortestSeq(int[] big, int[] small) { + int cnt = small.length; + Map need = new HashMap<>(cnt); + Map window = new HashMap<>(cnt); + for (int x : small) { + need.put(x, 1); + } + int k = -1, mi = 1 << 30; + for (int i = 0, j = 0; i < big.length; ++i) { + window.merge(big[i], 1, Integer::sum); + if (need.getOrDefault(big[i], 0) >= window.get(big[i])) { + --cnt; + } + while (cnt == 0) { + if (i - j + 1 < mi) { + mi = i - j + 1; + k = j; + } + if (need.getOrDefault(big[j], 0) >= window.get(big[j])) { + ++cnt; + } + window.merge(big[j++], -1, Integer::sum); + } + } + return k < 0 ? new int[0] : new int[] {k, k + mi - 1}; + } +} \ No newline at end of file diff --git a/lcci/17.18.Shortest Supersequence/Solution.py b/lcci/17.18.Shortest Supersequence/Solution.py new file mode 100644 index 0000000000000..549ef7c2f74b3 --- /dev/null +++ b/lcci/17.18.Shortest Supersequence/Solution.py @@ -0,0 +1,18 @@ +class Solution: + def shortestSeq(self, big: List[int], small: List[int]) -> List[int]: + need = Counter(small) + window = Counter() + cnt, j, k, mi = len(small), 0, -1, inf + for i, x in enumerate(big): + window[x] += 1 + if need[x] >= window[x]: + cnt -= 1 + while cnt == 0: + if i - j + 1 < mi: + mi = i - j + 1 + k = j + if need[big[j]] >= window[big[j]]: + cnt += 1 + window[big[j]] -= 1 + j += 1 + return [] if k < 0 else [k, k + mi - 1] diff --git a/lcci/17.18.Shortest Supersequence/Solution.ts b/lcci/17.18.Shortest Supersequence/Solution.ts new file mode 100644 index 0000000000000..8cee6daaa419b --- /dev/null +++ b/lcci/17.18.Shortest Supersequence/Solution.ts @@ -0,0 +1,28 @@ +function shortestSeq(big: number[], small: number[]): number[] { + let cnt = small.length; + const need: Map = new Map(); + const window: Map = new Map(); + for (const x of small) { + need.set(x, 1); + } + let k = -1; + let mi = 1 << 30; + for (let i = 0, j = 0; i < big.length; ++i) { + window.set(big[i], (window.get(big[i]) ?? 0) + 1); + if ((need.get(big[i]) ?? 0) >= window.get(big[i])!) { + --cnt; + } + while (cnt === 0) { + if (i - j + 1 < mi) { + mi = i - j + 1; + k = j; + } + if ((need.get(big[j]) ?? 0) >= window.get(big[j])!) { + ++cnt; + } + window.set(big[j], window.get(big[j])! - 1); + ++j; + } + } + return k < 0 ? [] : [k, k + mi - 1]; +}