LeetCode每日一题(2561. Rearranging Fruits)

这篇博客探讨了如何以最低成本使两个包含不同水果成本的篮子变得相等。介绍了两种交换策略,并提供了示例解释如何计算交换成本。通过统计每个篮子中水果的频率,确定是否可能达到相等,并提出通过排序优化交换策略来最小化总成本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

You have two fruit baskets containing n fruits each. You are given two 0-indexed integer arrays basket1 and basket2 representing the cost of fruit in each basket. You want to make both baskets equal. To do so, you can use the following operation as many times as you want:

Chose two indices i and j, and swap the ith fruit of basket1 with the jth fruit of basket2.
The cost of the swap is min(basket1[i],basket2[j]).
Two baskets are considered equal if sorting them according to the fruit cost makes them exactly the same baskets.

Return the minimum cost to make both the baskets equal or -1 if impossible.

Example 1:

Input: basket1 = [4,2,2,2], basket2 = [1,4,1,2]
Output: 1

Explanation: Swap index 1 of basket1 with index 0 of basket2, which has cost 1. Now basket1 = [4,1,2,2] and basket2 = [2,4,1,2]. Rearranging both the arrays makes them equal.

Example 2:

Input: basket1 = [2,3,4,1], basket2 = [3,2,5,1]
Output: -1

Explanation: It can be shown that it is impossible to make both the baskets equal.

Constraints:

  • basket1.length == bakste2.length
  • 1 <= basket1.length <= 105
  • 1 <= basket1[i],basket2[i] <= 109

进行交换的方式有两种, 一种是 basket1[i]与 basket2[j]直接交换, 另一种是 basket1[i]或者 basket2[j]分别跟篮子中的最小值进行交换, 举个例子:

basket1 = [1, 2, 3, 3]
basket2 = [1, 2, 4, 4]

第一种方法是 basket1[2]与 basket2[2]直接进行交换, 得到:
basket1 = [1, 2, 4, 3]
basket2 = [1, 2, 3, 4]

第二种方法是 basket1[2]先与 basket2[0]进行交换, 得到:
basket1 = [1, 2, 1, 3]
basket2 = [3, 2, 4, 4]
然后再将 basket1[2]与 basket2[2]进行交换, 得到:
basket1 = [1, 2, 4, 3]
basket2 = [3, 2, 1, 4]

每次交换的成本如果是直接交换的话就是 min(basket1[i], basket2[j])或者 2 * min(basket1[…], basket2[…])

至于要交换的数字, 我们可以分别统计出 basket1 与 basket2 中数字的出现频次 freqs1 与 freqs2, 对于任何一个数字 n, 如果 freqs1[n] == freqs2[n]则不用进行交换, 如果(freqs1[n] + freqs2[n]) % 2 == 1, 则证明无法通过交换来实现两个篮子相等。如果可以进行交换, 则要交换的数量是 abs(freqs1[n] - freqs2[n]) / 2。这样我们可以把要交换的数字都放到一个数组 swaps 里, 因为是两两交换, 所以实际交换的次数应该是 swaps.len() / 2。也就是我们要把 swaps 里的数字两两配对, 使得 sum(min(swaps[i], swaps[j]))最小。看到这应该就都明白了, 实际就是将 swaps 排序后的 sum(swaps[…swaps.len() / 2])



use std::collections::HashMap;

impl Solution {
    pub fn min_cost(basket1: Vec<i32>, basket2: Vec<i32>) -> i64 {
        let min = *basket1.iter().chain(basket2.iter()).min().unwrap();
        let freqs1 = basket1.into_iter().fold(HashMap::new(), |mut m, v| {
            *m.entry(v).or_insert(0) += 1;
            m
        });
        let freqs2 = basket2.into_iter().fold(HashMap::new(), |mut m, v| {
            *m.entry(v).or_insert(0) += 1;
            m
        });
        let mut swap1 = Vec::new();
        let mut swap2 = Vec::new();
        for (&k1, &c1) in &freqs1 {
            let &c2 = freqs2.get(&k1).unwrap_or(&0);
            if c1 == c2 {
                continue;
            }
            if (c1 + c2) % 2 == 1 {
                return -1;
            }
            if c1 > c2 {
                swap1.append(&mut vec![k1; (c1 - c2) as usize / 2]);
            }
        }
        for (&k2, &c2) in &freqs2 {
            let &c1 = freqs1.get(&k2).unwrap_or(&0);
            if c1 == c2 {
                continue;
            }
            if (c1 + c2) % 2 == 1 {
                return -1;
            }
            if c2 > c1 {
                swap2.append(&mut vec![k2; (c2 - c1) as usize / 2]);
            }
        }
        swap1.sort();
        swap2.sort();
        swap2.reverse();
        let mut ans = 0;
        for (s1, s2) in swap1.into_iter().zip(swap2) {
            ans += s1.min(s2).min(min * 2) as i64;
        }
        ans
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值