[LeetCode] 2134. Minimum Swaps to Group All 1s Together II
A swap is defined as taking two distinct positions in an array and swapping the values in them.
A circular array is defined as an array where we consider the first element and the last element to be adjacent.
Given a binary circular array nums, return the minimum number of swaps required to group all 1's present in the array together at any location.
Example 1:
Input: nums = [0,1,0,1,1,0,0]
Output: 1
Explanation: Here are a few of the ways to group all the 1's together:
[0,0,1,1,1,0,0] using 1 swap.
[0,1,1,1,0,0,0] using 1 swap.
[1,1,0,0,0,0,1] using 2 swaps (using the circular property of the array).
There is no way to group all 1's together with 0 swaps.
Thus, the minimum number of swaps required is 1.
Example 2:
Input: nums = [0,1,1,1,0,0,1,1,0]
Output: 2
Explanation: Here are a few of the ways to group all the 1's together:
[1,1,1,0,0,0,0,1,1] using 2 swaps (using the circular property of the array).
[1,1,1,1,1,0,0,0,0] using 2 swaps.
There is no way to group all 1's together with 0 or 1 swaps.
Thus, the minimum number of swaps required is 2.
Example 3:
Input: nums = [1,1,0,0,1]
Output: 0
Explanation: All the 1's are already grouped together due to the circular property of the array.
Thus, the minimum number of swaps required is 0.
Constraints:
1 <= nums.length <= 105
nums[i] is either 0 or 1.
最少交换次数来组合所有的 1 II。
交换 定义为选中一个数组中的两个 互不相同 的位置并交换二者的值。 环形 数组是一个数组,可以认为 第一个 元素和 最后一个 元素 相邻 。 给你一个 二进制环形 数组 nums ,返回在 任意位置 将数组中的所有 1 聚集在一起需要的最少交换次数。
思路一
这道题跟版本一 1151 题很像,唯一不同的地方是题目多了一个条件,给的 input 是环形数组。环形数组中找连续的 1 的个数稍微有些复杂,因为最优解有可能是断开的(一部分 1 在数组起点,一部分 1 在数组终点),但是我们可以换一种思路。因为 input 数组中只有 0 和 1 两种数字,那么我们可以试着比较把所有的 1 聚集在一起的开销少还是把所有的 0 聚集在一起的开销少。
复杂度
时间O(n)
空间O(1)
代码
Java实现
class Solution { public int minSwaps(int[] nums) { int n = nums.length; int ones = 0; int zeros = 0; for (int num : nums) { if (num == 0) { zeros++; } } ones = n - zeros; int a = helper(nums, 0, zeros); int b = helper(nums, 1, ones); return Math.min(a, b); } private int helper(int[] nums, int target, int p) { int start = 0; int end = 0; int count = 0; int res = Integer.MAX_VALUE; while (end < nums.length) { if (nums[end] == target) { count++; } end++; if (end - start == p) { res = Math.min(res, p - count); if (nums[start] == target) { count--; } start++; } } return res; } }
思路二
固定 size 的滑动窗口。对于一个长度为 n 的数组而言,因为 1 有可能分布在数组的两端,所以我们可以通过扫描一个 2n 的长度来确保扫描到所有的 1。记得要对下标取模。
复杂度
时间O(n)
空间O(1)
代码
Java实现
class Solution { public int minSwaps(int[] nums) { int n = nums.length; int k = 0; for (int num : nums) { if (num == 1) { k++; } } int count = 0; // first k for (int i = 0; i < k; i++) { if (nums[i] == 1) { count++; } } int swap = k - count; for (int i = k; i < 2 * n; i++) { if (nums[i % n] == 1) { count++; } if (nums[(i - k) % n] == 1) { count--; } swap = Math.min(swap, k - count); } return swap; } } // sliding window with fixed size
相关题目
1151. Minimum Swaps to Group All 1s Together 2134. Minimum Swaps to Group All 1s Together II
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步