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
}
}