跳转至

3555. 排序每个滑动窗口中最小的子数组 🔒

题目描述

给定一个整数数组 nums 和一个整数 k

对于每个长度为 k 的连续 子数组,确定必须排序的连续段的最小长度,以便整个窗口成为 非递减 的;如果窗口已经排序,则其所需长度为零。

返回一个长度为 n − k + 1 的数组,其中每个元素对应其窗口的答案。

 

示例 1:

输入:nums = [1,3,2,4,5], k = 3

输出:[2,2,0]

解释:

  • nums[0...2] = [1, 3, 2]。排序 [3, 2] 得到 [1, 2, 3],答案是 2。
  • nums[1...3] = [3, 2, 4]。排序 [3, 2] 得到 [2, 3, 4],答案是 2。
  • nums[2...4] = [2, 4, 5] 已经有序,所以答案是 0。

示例 2:

输入:nums = [5,4,3,2,1], k = 4

输出:[4,4]

解释:

  • nums[0...3] = [5, 4, 3, 2]。整个子数组必须有序,所以答案是4。
  • nums[1...4] = [4, 3, 2, 1]。整个子数组必须有序,所以答案是4。

 

提示:

  • 1 <= nums.length <= 1000
  • 1 <= k <= nums.length
  • 1 <= nums[i] <= 106

解法

方法一:枚举 + 维护左侧最大值和右侧最小值

我们可以枚举每个长度为 \(k\) 的子数组,对于每个子数组 \(nums[i...i + k - 1]\),我们需要找到最小的连续段,使得排序后整个子数组都是非递减的。

对于子数组 \(nums[i...i + k - 1]\),我们可以从左到右遍历数组,维护一个最大值 \(mx\),如果当前值小于 \(mx\),说明当前值不在正确的位置上,我们更新右边界 \(r\) 为当前位置。同理,我们可以从右到左遍历数组,维护一个最小值 \(mi\),如果当前值大于 \(mi\),说明当前值不在正确的位置上,我们更新左边界 \(l\) 为当前位置。在初始化时,我们将 \(l\)\(r\) 都初始化为 \(-1\),如果 \(l\)\(r\) 都没有被更新,说明数组已经有序,返回 \(0\),否则返回 \(r - l + 1\)

时间复杂度 \(O(n \times k)\),其中 \(n\) 是数组 \(\textit{nums}\) 的长度。空间复杂度 \(O(1)\)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
class Solution:
    def minSubarraySort(self, nums: List[int], k: int) -> List[int]:
        def f(i: int, j: int) -> int:
            mi, mx = inf, -inf
            l = r = -1
            for k in range(i, j + 1):
                if mx > nums[k]:
                    r = k
                else:
                    mx = nums[k]
                p = j - k + i
                if mi < nums[p]:
                    l = p
                else:
                    mi = nums[p]
            return 0 if r == -1 else r - l + 1

        n = len(nums)
        return [f(i, i + k - 1) for i in range(n - k + 1)]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Solution {
    private int[] nums;
    private final int inf = 1 << 30;

    public int[] minSubarraySort(int[] nums, int k) {
        this.nums = nums;
        int n = nums.length;
        int[] ans = new int[n - k + 1];
        for (int i = 0; i < n - k + 1; ++i) {
            ans[i] = f(i, i + k - 1);
        }
        return ans;
    }

    private int f(int i, int j) {
        int mi = inf, mx = -inf;
        int l = -1, r = -1;
        for (int k = i; k <= j; ++k) {
            if (nums[k] < mx) {
                r = k;
            } else {
                mx = nums[k];
            }
            int p = j - k + i;
            if (nums[p] > mi) {
                l = p;
            } else {
                mi = nums[p];
            }
        }
        return r == -1 ? 0 : r - l + 1;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public:
    vector<int> minSubarraySort(vector<int>& nums, int k) {
        const int inf = 1 << 30;
        int n = nums.size();
        auto f = [&](int i, int j) -> int {
            int mi = inf, mx = -inf;
            int l = -1, r = -1;
            for (int k = i; k <= j; ++k) {
                if (nums[k] < mx) {
                    r = k;
                } else {
                    mx = nums[k];
                }
                int p = j - k + i;
                if (nums[p] > mi) {
                    l = p;
                } else {
                    mi = nums[p];
                }
            }
            return r == -1 ? 0 : r - l + 1;
        };
        vector<int> ans;
        for (int i = 0; i < n - k + 1; ++i) {
            ans.push_back(f(i, i + k - 1));
        }
        return ans;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
func minSubarraySort(nums []int, k int) []int {
    const inf = 1 << 30
    n := len(nums)
    f := func(i, j int) int {
        mi := inf
        mx := -inf
        l, r := -1, -1
        for p := i; p <= j; p++ {
            if nums[p] < mx {
                r = p
            } else {
                mx = nums[p]
            }
            q := j - p + i
            if nums[q] > mi {
                l = q
            } else {
                mi = nums[q]
            }
        }
        if r == -1 {
            return 0
        }
        return r - l + 1
    }

    ans := make([]int, 0, n-k+1)
    for i := 0; i <= n-k; i++ {
        ans = append(ans, f(i, i+k-1))
    }
    return ans
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function minSubarraySort(nums: number[], k: number): number[] {
    const inf = Infinity;
    const n = nums.length;
    const f = (i: number, j: number): number => {
        let mi = inf;
        let mx = -inf;
        let l = -1,
            r = -1;
        for (let p = i; p <= j; ++p) {
            if (nums[p] < mx) {
                r = p;
            } else {
                mx = nums[p];
            }
            const q = j - p + i;
            if (nums[q] > mi) {
                l = q;
            } else {
                mi = nums[q];
            }
        }
        return r === -1 ? 0 : r - l + 1;
    };

    const ans: number[] = [];
    for (let i = 0; i <= n - k; ++i) {
        ans.push(f(i, i + k - 1));
    }
    return ans;
}

评论