[LeetCode] 1151. Minimum Swaps to Group All 1's Together

Given a binary array data, return the minimum number of swaps required to group all 1’s present in the array together in any place in the array.

Example 1:
Input: data = [1,0,1,0,1]
Output: 1
Explanation: There are 3 ways to group all 1's together:
[1,1,1,0,0] using 1 swap.
[0,1,1,1,0] using 2 swaps.
[0,0,1,1,1] using 1 swap.
The minimum is 1.

Example 2:
Input: data = [0,0,0,1,0]
Output: 0
Explanation: Since there is only one 1 in the array, no swaps are needed.

Example 3:
Input: data = [1,0,1,0,1,0,0,1,1,0,1]
Output: 3
Explanation: One possible solution that uses 3 swaps is [0,0,0,0,0,1,1,1,1,1,1].

Constraints:
1 <= data.length <= 105
data[i] is either 0 or 1.

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

给出一个二进制数组 data,你需要通过交换位置,将数组中所有的 1 组合到一起,并返回所有可能中所需最少的交换次数。

思路

这道题问的是 swap 的次数,注意 swap 的策略是有好坏的,这也就是为什么例子一有三种 swap 的结果但是这三种策略的代价是不一样的。我这里提供一个滑动窗口的思路。这道题前缀和也能做,日后有时间我再补充。注意这道题的滑动窗口尺寸是固定的。滑动窗口的尺寸就是 1 的个数。

首先我们用一个变量 ones 记录 input 数组中一共有多少个 1。然后我们用滑动窗口的模板开始扫描 input 数组,当 end 指针遇到 1 的时候,count++;当 end 和 start 两个指针的距离 == ones 的时候,此时我们看一下 end 和 start 之间有几个 1,此时 ones 和 count 的差值就是需要 swap 的次数。遍历整个数组,找到全局最小的 swap 次数即可。

复杂度

时间O(n)
空间O(1)

代码一

Java实现

class Solution {
    public int minSwaps(int[] data) {
        int ones = 0;
        for (int d : data) {
            if (d == 1) {
                ones++;
            }
        }
        // corner case
        if (ones == 0) {
            return 0;
        }

        // normal case
        int start = 0;
        int end = 0;
        int count = 0;
        int res = Integer.MAX_VALUE;
        while (end < data.length) {
            if (data[end] == 1) {
                count++;
            }
            end++;
            if (end - start == ones) {
                res = Math.min(res, ones - count);
                if (data[start] == 1) {
                    count--;
                }
                start++;
            }
        }
        return res;
    }
}

代码二

这里我再提供一个 for 循环的代码。因为这道题滑动窗口的 size 是固定的,所以 for 循环也能做。
Java实现

class Solution {
    public int minSwaps(int[] data) {
        // 统计一共有多少个1
        int ones = 0;
        for (int d : data) {
            if (d == 1) {
                ones++;
            }
        }

        // 统计前ones个位置上有多少个1
        int c = 0;
        for (int i = 0; i < ones; i++) {
            if (data[i] == 1) {
                c++;
            }
        }
        // corner case
        // 如果1都在一开始的位置上,则无需swap
        if (c == ones) {
            return 0;
        }

        // normal case
        // min是一开始的位置上需要swap的次数
        int min = ones - c;
        int k = c;
        for (int j = ones; j < data.length; j++) {
            if (data[j] == 1) {
                k++;
            }
            if (data[j - ones] == 1) {
                k--;
            }
            min = Math.min(min, ones - k);
        }
        return min;
    }
}

相关题目

1151. Minimum Swaps to Group All 1s Together
2134. Minimum Swaps to Group All 1s Together II
posted @ 2021-03-11 03:04  CNoodle  阅读(854)  评论(0)    收藏  举报