交换 定义为选中一个数组中的两个 互不相同 的位置并交换二者的值。
环形 数组是一个数组,可以认为 第一个 元素和 最后一个 元素 相邻
给你一个 二进制环形 数组 nums ,返回在 任意位置 将数组中的所有 1 聚集在一起需要的最少交换次数。
示例 1:

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

    解法一:滑窗

    当遇到这种相邻元素时,应该首先要考虑到滑窗。

  • 这里由于是可以成环,那么可以将滑窗的初始状态置为 [n - width, n)这时候 left 是 n-width,而right 是 0,滑窗开始后,当 left 的结果大于 n 时,我们可以取余即可 ```go func minSwaps(nums []int) int { n := len(nums) width := 0 res := math.MaxInt32 for _, num := range nums {

      if num == 1 {
          width++
      }
    

    } if width == 0 || width == n {

      return 0
    

    } left, right := n - width, 0 count := 0 for i := left; i< n;i++ {

      if nums[i] == 1 {
          count++
      }
    

    } for right < n {

      res = min(res, width - count)
      if nums[right] == 1 {
          count++
      }
      if nums[left] == 1 {
          count--
      }
      left++
      left %= n
      right++
    

    } return res }

func min (a, b int) int { if a > b { return b } return a } ```