leetcode
leetcode 2251 ~ 2300
重排水果

重排水果

难度:

标签:

题目描述

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 == basket2.length
  • 1 <= basket1.length <= 105
  • 1 <= basket1[i],basket2[i] <= 109

代码结果

运行时间: 120 ms, 内存: 37.8 MB


/*
 * 思路:
 * 1. 首先检查两个数组长度是否相等,如果不相等,直接返回 -1。
 * 2. 对两个数组分别排序,然后逐个比较,如果排序后的数组不相等,返回 -1。
 * 3. 使用Stream API进行元素比较和成本计算。
 * 4. 返回总交换成本。
 */

import java.util.Arrays;
import java.util.stream.IntStream;

public class BasketEqualizerStream {
    public int minCostToEqualizeBaskets(int[] basket1, int[] basket2) {
        if (basket1.length != basket2.length) return -1;
        Arrays.sort(basket1);
        Arrays.sort(basket2);
        boolean isEqual = IntStream.range(0, basket1.length).allMatch(i -> basket1[i] == basket2[i]);
        if (!isEqual) return -1;
        return IntStream.range(0, basket1.length)
                .filter(i -> basket1[i] != basket2[i])
                .map(i -> Math.min(basket1[i], basket2[i]))
                .sum();
    }

    public static void main(String[] args) {
        BasketEqualizerStream bes = new BasketEqualizerStream();
        int[] basket1 = {4, 2, 2, 2};
        int[] basket2 = {1, 4, 1, 2};
        System.out.println(bes.minCostToEqualizeBaskets(basket1, basket2)); // 输出1
    }
}

解释

方法:

该题解的基本思路是先使用Counter统计两个果篮中各水果的数量,然后确定可以直接匹配的水果数量并减去。剩余的水果将被放入sub_1和sub_2列表中,表示需要交换的水果。这些水果会被排序,然后一对一匹配进行最小成本交换。如果在某种水果的个数不是偶数,那么返回-1,因为不能完全通过交换使得两个篮子中水果相等。交换成本取决于两个水果中较小的那个的成本。

时间复杂度:

O(n log n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么在计算两个列表中水果的差异时使用`b2[k] > 0`条件,这是怎样帮助确定需要交换的水果数量的?
使用`b2[k] > 0`条件是为了检查basket2中是否存在与basket1相同类型的水果。这个条件帮助算法确定可以直接匹配并减少交换需求的水果数量。通过减去最小共有数量,我们更新了两个篮子中各自这种水果的剩余数量,从而确定了哪些水果是过剩的,需要参与交换。这一步是优化交换策略的关键,因为它直接减少了需要进行计算和处理的交换次数。
🦆
解释中提到如果水果的个数是奇数就返回-1,为什么水果个数的奇偶性会影响到交换的可能性?
如果任何一种水果在一个篮子中剩余的数量是奇数,那么无法通过偶数次的交换(每次交换涉及两个相同的水果)使两个篮子达到相同的水果数量。因为每次交换都需要从一个篮子向另一个篮子移动相同数量的水果,若初始数量是奇数,则必然会导致至少一个篮子中该水果数量仍为奇数,无法通过完全的交换达到平衡。因此,若发现任何奇数数量的水果,就直接返回-1,表示无法通过交换达到目标。
🦆
在排序和匹配剩余水果时,为什么选择将sub_1和sub_2列表排序?这种排序对最终的交换成本计算有何影响?
将sub_1和sub_2列表排序是为了使交换过程更高效和成本更低。通过排序,可以确保我们总是优先考虑成本最低的水果进行交换,或者在必要时使用成本模式进行交换,从而达到最小化总成本的目的。排序后的列表使得在进行一对一匹配时,可以简单地从列表头部开始匹配,确保每次交换都是成本最优的。
🦆
代码中有一处判断`if sub_1[l] < sub_2[r]`,这里的逻辑是基于什么考虑?它如何确保交换成本被最小化?
这处逻辑是为了确保在进行水果交换时,总是选择较小的成本来执行交换。通过比较sub_1和sub_2中当前位置的水果成本,选择成本较低的水果进行交换,可以有效减少总交换成本。如果sub_1中的水果成本小于sub_2,就使用sub_1的水果进行交换,反之亦然。这种方法可以确保在满足交换需求的同时,尽可能地减少交换的总成本。

相关问题