leetcode
leetcode 1851 ~ 1900
最少交换次数来组合所有的 1 II

最少交换次数来组合所有的 1 II

难度:

标签:

题目描述

代码结果

运行时间: 85 ms, 内存: 21.0 MB


/*
 * 题目思路:
 * 1. 计算总的 1 的数量 totalOnes。
 * 2. 利用 Stream 计算总的 1 的数量,以及滑动窗口中的 1 的数量。
 * 3. 对于数组的每一个位置,计算其滑动窗口中 1 的最大数量。
 */
import java.util.stream.IntStream;

public class MinSwapsStream {
    public int minSwaps(int[] nums) {
        int totalOnes = (int) IntStream.of(nums).filter(num -> num == 1).count();
        int n = nums.length;

        int maxOnes = IntStream.range(0, totalOnes)
                                .map(i -> nums[i])
                                .sum();

        int currentOnes = maxOnes;

        for (int i = 1; i < n; i++) {
            currentOnes += nums[(i + totalOnes - 1) % n] - nums[i - 1];
            maxOnes = Math.max(maxOnes, currentOnes);
        }

        return totalOnes - maxOnes;
    }
}

解释

方法:

The solution uses a sliding window approach. First, it counts the number of 1s in the array and duplicates the array to handle the circular nature. Then, it creates a window of size equal to the number of 1s and slides it across the array to find the maximum number of 1s that can be gathered in one window. The minimum number of swaps is then calculated by subtracting this maximum from the total count of 1s.

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么先统计数组中`1`的数量再将数组翻倍,翻倍的目的是什么?
首先统计数组中`1`的数量是为了确定滑动窗口的大小,这个大小等于1的总数量,因为我们的目标是尽可能地将所有的1集中到一个连续的区域中。数组翻倍是因为这个问题的数组是环形的,翻倍后可以简化环形数组边界条件的处理。通过翻倍,原本环形的结构被线性化,使得可以用常规的滑动窗口方法来处理可能跨越数组起始和结束边界的情况。
🦆
在使用滑动窗口法时,如何处理环形数组的边界条件?
在处理环形数组的边界条件时,通过将数组翻倍来模拟环形结构。这样,可以在一个长度为2倍原数组长度的线性数组上应用滑动窗口,而不必担心窗口跨越数组的起始和结束边界。滑动窗口只需在长度为原数组长度的范围内移动,从而能够覆盖所有可能的连续区域,包括那些跨越原数组边界的区域。
🦆
在计算滑动窗口中的1的数量时,为什么通过`cnt_ += nums[i + cnt] - nums[i]`更新计数,这种更新方式的正确性如何保证?
这种更新计数的方法是基于滑动窗口的性质。当窗口向右滑动一位时,窗口最左边的元素(nums[i])会被移出窗口,而紧接在窗口最右边的下一个元素(nums[i + cnt])将进入窗口。因此,更新1的数量就是简单地加上新进入窗口的元素值(nums[i + cnt],如果是1就加1,是0就加0),并减去移出窗口的元素值(nums[i])。这样可以快速计算出新窗口中1的总数量,而无需重新遍历整个窗口。
🦆
请解释为什么最少交换次数是通过`cnt - ans`计算得到的?这里的`ans`代表什么?
`ans`在此题解中代表在任意连续的由`cnt`个元素组成的窗口中,能够找到的最大的1的数量。因此,`cnt - ans`就是在最优情况下,即1已经尽可能多地聚集在一起时,窗口中还需要通过交换添加的1的数量,这也就是最少需要进行的交换次数。这是因为如果一个窗口已经包含了尽可能多的1,那么窗口外剩余的1就需要与窗口内的0进行交换,以实现所有1的聚集。

相关问题