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


交换 定义为选中一个数组中的两个 互不相同 的位置并交换二者的值。

环形 数组是一个数组,可以认为 第一个 元素和 最后一个 元素 相邻

给你一个 二进制环形 数组 nums ,返回在 任意位置 将数组中的所有 1 聚集在一起需要的最少交换次数。

示例 1:

输入:nums = [0,1,0,1,1,0,0]
输出:1
解释:这里列出一些能够将所有 1 聚集在一起的方案:
[0,0,1,1,1,0,0] 交换 1 次。
[0,1,1,1,0,0,0] 交换 1 次。
[1,1,0,0,0,0,1] 交换 2 次(利用数组的环形特性)。
无法在交换 0 次的情况下将数组中的所有 1 聚集在一起。
因此,需要的最少交换次数为 1 。

示例 2:

输入:nums = [0,1,1,1,0,0,1,1,0]
输出:2
解释:这里列出一些能够将所有 1 聚集在一起的方案:
[1,1,1,0,0,0,0,1,1] 交换 2 次(利用数组的环形特性)。
[1,1,1,1,1,0,0,0,0] 交换 2 次。
无法在交换 0 次或 1 次的情况下将数组中的所有 1 聚集在一起。
因此,需要的最少交换次数为 2 。

示例 3:

输入:nums = [1,1,0,0,1]
输出:0
解释:得益于数组的环形特性,所有的 1 已经聚集在一起。
因此,需要的最少交换次数为 0 。

提示:

  • 1 <= nums.length <= 10^5
  • nums[i]0 或者 1
class Solution {
    public int minSwaps(int[] nums) {
        // 完全想象不到这个题要用滑动窗口!!!!
        // 思路要转变一下了.,一般的滑动窗口入参是一个数组和一个限制的长度,这个入参只提供了一个数组,限制长度由算法中计算出来。
        // 这个问题可以得知,得到1个连续都是1的环形数组,即,得知n的长度,然后再从0开始,能满足这个长度.
        // 滑窗内统计1的个数,再用总个数减去
        // 记录数组中1的个数
        int count = 0;
        int len = nums.length;
        for (int i = 0; i < len; i++) {
            count = count + nums[i];
        }
        //此时可以确认滑动窗口的长度为 count;

        int num = 0; //看看最开始的情况下,有几个1
        for(int i = 0; i < count; i++){
            num = num + nums[i];
        }

        // 设置结果为 1的值
        int result = num;

        for(int i = 0;i < len - 1; i++){
            //注意了!!! 注意了!!! 关注点都在 nums[(count+i)%nums.length] 这里才对。
            // (count+i)%len 本质上就是循环数组
            //举例说明 [0,1,0,1,1,0,0]:count是3个,前3个中有1个1,(3+0) % 7 = 3 
            // 
            num  = num + nums[(count+i)%len] - nums[i];
            result = Math.max(result,num);
        }
    
        return count- result;
    }
}

文章作者: 冯廷鑫
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 冯廷鑫 !
  目录