通过最少操作次数使数组的和相等

238 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情

通过最少操作次数使数组的和相等

题目

给你两个长度可能不等的整数数组 nums1 和 nums2 。两个数组中的所有值都在 1 到 6 之间(包含 1 和 6)。 每次操作中,你可以选择 任意 数组中的任意一个整数,将它变成 1 到 6 之间 任意 的值(包含 1 和 6)。 请你返回使 nums1 中所有数的和与 nums2 中所有数的和相等的最少操作次数。如果无法使两个数组的和相等,请返回 -1 。

  • 1 <= nums1.length, nums2.length <= 105
  • 1 <= nums1[i], nums2[i] <= 6

题目要求我们让两个数组的和相等

抛开其他的不谈,对于两个值,要想让他们相等,那么就是一个双向奔赴的过程啦!

那么,对于双向奔赴来说,我们要找出最小的步数

那么,我们原数组中增加或者减小对应着什么呢?

对应着我们比较大的数组的减小和比较小的数组的增大

大的数组减小最少为11,所以对于每一个位置可以减小的值为 v1v - 1

小的数组增大最大为66,所以对于每一个位置可以增大的值为 6v6 - v

然后,我们将其存入优先队列中去,优先考虑减去大的差值

假设我们的差值为 kk,每次从队列中取出最大的差值,减去。

这样我们可以保证,我们的差值k可以在最快的速度里面到达00的位置

这样,我们就可以实现最优化操作了

use std::collections::{BinaryHeap};
use std::mem::swap;
impl Solution {
    pub fn min_operations(a: Vec<i32>, b: Vec<i32>) -> i32 {
        if a.len() * 6 < b.len() || b.len() * 6 < a.len() {
            return -1;
        }
        let (mut a, mut b) = (a, b);
        let (mut n, mut m) = (a.len(), b.len());
        let (mut s1, mut s2): (i32, i32) = (a.iter().sum(), b.iter().sum());
        let mut pq = BinaryHeap::new();
        if s1 < s2 {
            swap(&mut s1, &mut s2);
            swap(&mut a, &mut b);
        }
        a.iter().for_each(|&v| pq.push(v - 1));
        b.iter().for_each(|&v| pq.push(6 - v));
        let (mut ans, mut k) = (0, s1 - s2);
        while k > 0 {
            ans += 1;
            k -= pq.pop().unwrap();
        }
        ans
    }
}