leetcode
leetcode 2301 ~ 2350
滑动子数组的美丽值

滑动子数组的美丽值

难度:

标签:

题目描述

Given an integer array nums containing n integers, find the beauty of each subarray of size k.

The beauty of a subarray is the xth smallest integer in the subarray if it is negative, or 0 if there are fewer than x negative integers.

Return an integer array containing n - k + 1 integers, which denote the beauty of the subarrays in order from the first index in the array.

  • A subarray is a contiguous non-empty sequence of elements within an array.

 

Example 1:

Input: nums = [1,-1,-3,-2,3], k = 3, x = 2
Output: [-1,-2,-2]
Explanation: There are 3 subarrays with size k = 3. 
The first subarray is [1, -1, -3] and the 2nd smallest negative integer is -1. 
The second subarray is [-1, -3, -2] and the 2nd smallest negative integer is -2. 
The third subarray is [-3, -2, 3] and the 2nd smallest negative integer is -2.

Example 2:

Input: nums = [-1,-2,-3,-4,-5], k = 2, x = 2
Output: [-1,-2,-3,-4]
Explanation: There are 4 subarrays with size k = 2.
For [-1, -2], the 2nd smallest negative integer is -1.
For [-2, -3], the 2nd smallest negative integer is -2.
For [-3, -4], the 2nd smallest negative integer is -3.
For [-4, -5], the 2nd smallest negative integer is -4. 

Example 3:

Input: nums = [-3,1,2,-3,0,-3], k = 2, x = 1
Output: [-3,0,-3,-3,-3]
Explanation: There are 5 subarrays with size k = 2.
For [-3, 1], the 1st smallest negative integer is -3.
For [1, 2], there is no negative integer so the beauty is 0.
For [2, -3], the 1st smallest negative integer is -3.
For [-3, 0], the 1st smallest negative integer is -3.
For [0, -3], the 1st smallest negative integer is -3.

 

Constraints:

  • n == nums.length 
  • 1 <= n <= 105
  • 1 <= k <= n
  • 1 <= x <= k 
  • -50 <= nums[i] <= 50 

代码结果

运行时间: 375 ms, 内存: 25.9 MB


import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 给定一个整数数组 nums 和两个整数 k 和 x, 使用 Java Stream API 求出每个长度为 k 的子数组的美丽值。
 * 美丽值定义为:如果子数组中第 x 小的整数是负数,则美丽值为该数;否则为 0。
 */
public class Solution {
    public int[] getBeautyValues(int[] nums, int k, int x) {
        return IntStream.rangeClosed(0, nums.length - k)
                .map(i -> Arrays.stream(nums, i, i + k)
                        .sorted()
                        .toArray()[x - 1])
                .map(value -> value < 0 ? value : 0)
                .toArray();
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        int[] nums = {1, -1, -3, -2, 3};
        int k = 3;
        int x = 2;
        System.out.println(Arrays.toString(sol.getBeautyValues(nums, k, x)));
    }
}

解释

方法:

此题解使用滑动窗口和直接数组索引的方法来维护和更新子数组内元素的计数,从而实时获取子数组内第x小的值。初始化时,首先统计前k个元素的计数,然后寻找当前第x小的值。在随后的滑动窗口操作中,对每次滑动窗口的移动,都会调整计数数组,并重新确定第x小的值。如果新计算出的第x小的值是负数,则记录此值;如果不是,则记录0。此方法避免了对每个窗口内的所有元素进行排序,大大提高了效率。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
在题解中提到使用计数数组d来维护子数组元素的计数,这种方法是否考虑了nums数组中可能存在的超出[-50, 50]范围的值?
题解中使用的计数数组d是基于nums数组中的元素只在[-50, 50]范围内的假设。如果nums中存在超出这个范围的值,则计数数组d无法正确地统计这些值,因此这种方法在该假设不成立时不适用。实际应用中需要根据数据的具体范围调整计数数组的大小和映射逻辑。
🦆
题解中提到,计数数组的大小为101,这是基于什么考虑?如果输入数组nums的范围更广,比如[-1000, 1000],这种方法还适用吗?
计数数组的大小为101是基于输入数组nums的值只在[-50, 50]之间这一假设。这样可以通过将值加50来直接映射到数组索引中。如果输入数组的范围是[-1000, 1000],则需要调整数组大小为2001,并相应地调整索引映射(即值加1000映射到索引)。这种方法在调整后仍然适用,但需要更多的空间和适当的索引调整。
🦆
在寻找第x小的数时,题解使用了线性遍历计数数组的方式,这种方式的效率如何?存在更优的查找方法吗?
线性遍历计数数组的方式在最坏情况下需要遍历整个计数数组,其时间复杂度为O(n),其中n是计数数组的长度。当计数数组很大时,这种方法可能会较慢。一个更优的查找方法是使用平衡二叉搜索树或优先队列来维护元素的计数,这样可以更快地找到第x小的数。例如,使用红黑树或AVL树,可以在O(log n)时间内完成插入、删除和查找操作。
🦆
题解中的滑动窗口更新过程中,对于每次窗口移动后重新计算第x小的值的过程中,是否有可能出现cnt计数错误的情况?如何确保其准确性?
在滑动窗口的更新过程中,确实可能出现cnt计数错误的情况,特别是在元素频率的增减处理上。要确保计数的准确性,需要仔细处理每个元素进入和离开窗口时对计数数组的更新。此外,每次更新后,检查cnt的值是否与窗口内元素的总数相符,可以通过遍历计数数组验证,确保每次更新后cnt的值正确反映了第x小值的位置。

相关问题