LeetCode 995.K 连续位的最小翻转次数

K 连续位的最小翻转次数

在仅包含 0 和 1 的数组 A 中,一次 K 位翻转包括选择一个长度为 K 的(连续)子数组,同时将子数组中的每个 0 更改为 1,而每个 1 更改为 0。

返回所需的 K 位翻转的最小次数,以便数组没有值为 0 的元素。如果不可能,返回 -1。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-number-of-k-consecutive-bit-flips
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

贪心算法

// 贪心算法, 遇到0就翻转
fn min_k_bit_flips(a: Vec<i32>, k: i32) -> i32 {
  let mut cnt = 0;
  let mut left = 0;
  let mut a_clone = a.clone();
  let k:usize = k as usize;
  while left < a_clone.len() + 1 - k as usize {
    if a_clone[left] == 0 {
      // 翻转
      for idx in 0..k {
        a_clone[idx + left] = 1 - a_clone[idx + left];
      }
      cnt += 1;
      print!("left:{}\t cnt:{}\t, {:?}\n", left, cnt, a_clone);
    }
    left += 1;
  }
  for idx in 0..k {
    let idx: usize = a_clone.len() - 1 - idx as usize;
    if a_clone[idx] == 0 {
      return -1;
    }
  }
  return cnt;
}

fn main() {
  let nums: Vec<i32> = vec![1,1,0];
  let k:i32 = 2;
  print!("output is {}\n", min_k_bit_flips(nums, k));
}
优化

分析得知,没有必要每次都做翻转的操作

思路

  1. 一个数组k,记录对应位置的翻转次数
  2. 第 i 位若要翻转, 这 区间[i, i+k]内的次数 都加1, 翻转总次数 + 1

需要考虑的几个问题

  1. 如何判断第 i 位是否要翻转???
    由于题目的特殊性: 这是一个只有0, 1 的数组 和 一个翻转的操作
    不难得知:即奇数次反转之后数字发生了变换, 偶数次转换还是该值
    所以 a[i + 1] == 0 && k[i] % 2 == 0或者 a[i + 1] == 1 && k[i] % 2 == 1时需要翻转
    综上 (a[i + 1] + k[i]) % 2 == 0时认为需要翻转

注意到 有一个对区间所有数都加一的操作, 这样可以考虑差分数组的思路

:

  1. 定义一个拆分数组
  2. 第 i 位若要翻转, 则 a[i] + 1, a[i + k] - 1, 这样对于第i位的翻转次数 就可以表示为∑ a[i] 可以用一个变量来记录

第一次优化后的代码:

fn min_k_bit_flips(a: Vec<i32>, k: i32) -> i32 {
  let mut left = 0;
  let mut cnt = 0;
  let mut diff_sum = 0;
  let mut diff = vec![0; a.len() + 1];
  let k:usize = k as usize;
  while left < a.len() {
    // 计算前n的和, 也就是第n位翻转的次数
    diff_sum += diff[left];
    if (a[left] + diff_sum) % 2 == 0 {
      // 需要翻转
      if left + k > a.len() {
        // 无法进行翻转
        return -1;
      }
      cnt += 1;
      diff[left] += 1; diff_sum += 1;
      diff[left + k] -= 1;
    }
    left += 1;
  }
  return cnt;
}




fn main() {
  let nums: Vec<i32> = vec![0,0,0,1,0,1,1,0];
  let k:i32 = 3;
  print!("output is {}\n", min_k_bit_flips(nums, k));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值