交换 定义为选中一个数组中的两个 互不相同 的位置并交换二者的值。
环形 数组是一个数组,可以认为 第一个 元素和 最后一个 元素 相邻 。
给你一个 二进制环形 数组 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 <= 105
nums[i]
为0
或者1
前缀和 + 滑动窗口。
class Solution:
def minSwaps(self, nums: List[int]) -> int:
cnt = nums.count(1)
n = len(nums)
s = [0] * ((n << 1) + 1)
for i in range(n << 1):
s[i + 1] = s[i] + nums[i % n]
mx = 0
for i in range(n << 1):
j = i + cnt - 1
if j < (n << 1):
mx = max(mx, s[j + 1] - s[i])
return cnt - mx
class Solution {
public int minSwaps(int[] nums) {
int cnt = 0;
for (int v : nums) {
cnt += v;
}
int n = nums.length;
int[] s = new int[(n << 1) + 1];
for (int i = 0; i < (n << 1); ++i) {
s[i + 1] = s[i] + nums[i % n];
}
int mx = 0;
for (int i = 0; i < (n << 1); ++i) {
int j = i + cnt - 1;
if (j < (n << 1)) {
mx = Math.max(mx, s[j + 1] - s[i]);
}
}
return cnt - mx;
}
}
function minSwaps(nums: number[]): number {
const n = nums.length;
const m = nums.reduce((a, c) => a + c, 0);
let cnt = nums.reduce((a, c, i) => a + (i < m ? c : 0), 0);
let ans = cnt;
for (let i = m; i < m + n; i++) {
let prev = nums[i - m];
let post = nums[i % n];
cnt += post - prev;
ans = Math.max(cnt, ans);
}
return m - ans;
}
class Solution {
public:
int minSwaps(vector<int>& nums) {
int cnt = 0;
for (int& v : nums) cnt += v;
int n = nums.size();
vector<int> s((n << 1) + 1);
for (int i = 0; i < (n << 1); ++i) s[i + 1] = s[i] + nums[i % n];
int mx = 0;
for (int i = 0; i < (n << 1); ++i) {
int j = i + cnt - 1;
if (j < (n << 1)) mx = max(mx, s[j + 1] - s[i]);
}
return cnt - mx;
}
};
func minSwaps(nums []int) int {
cnt := 0
for _, v := range nums {
cnt += v
}
n := len(nums)
s := make([]int, (n<<1)+1)
for i := 0; i < (n << 1); i++ {
s[i+1] = s[i] + nums[i%n]
}
mx := 0
for i := 0; i < (n << 1); i++ {
j := i + cnt - 1
if j < (n << 1) {
mx = max(mx, s[j+1]-s[i])
}
}
return cnt - mx
}
func max(a, b int) int {
if a > b {
return a
}
return b
}