Rearranging Fruits

hard greedy hash table sorting

Problem

Two baskets basket1 and basket2 each hold n fruit costs. One operation swaps basket1[i] with basket2[j] at cost min(basket1[i], basket2[j]). The baskets are equal when sorting both produces identical arrays. Return the minimum total cost to make them equal, or -1 if it is impossible.

Inputbasket1 = [4,2,2,2], basket2 = [1,4,1,2]
Output1
Swap basket1[1] = 2 with basket2[0] = 1 at cost min(2, 1) = 1. Both baskets then sort to the same multiset.

def minCost(basket1, basket2):
    count = {}                              # net surplus per value
    for x in basket1:
        count[x] = count.get(x, 0) + 1      # basket1 contributes +1
    for x in basket2:
        count[x] = count.get(x, 0) - 1      # basket2 contributes -1
    lo = min(min(basket1), min(basket2))    # global cheapest fruit
    merge = []
    for v, c in count.items():
        if c % 2 != 0:
            return -1                       # odd total -> impossible
        merge += [v] * (abs(c) // 2)        # half of each surplus moves
    merge.sort()                            # cheapest swaps first
    total = 0
    for i in range(len(merge) // 2):        # pay only the cheaper half
        total += min(merge[i], 2 * lo)      # direct swap or via lo
    return total
function minCost(basket1, basket2) {
  const count = new Map();                       // net surplus per value
  for (const x of basket1) count.set(x, (count.get(x) || 0) + 1);
  for (const x of basket2) count.set(x, (count.get(x) || 0) - 1);
  const lo = Math.min(...basket1, ...basket2);   // global cheapest fruit
  const merge = [];
  for (const [v, c] of count) {
    if (c % 2 !== 0) return -1;                   // odd total -> impossible
    for (let k = 0; k < Math.abs(c) / 2; k++) merge.push(v);
  }
  merge.sort((a, b) => a - b);                    // cheapest swaps first
  let total = 0;
  for (let i = 0; i < merge.length / 2; i++) {    // pay only the cheaper half
    total += Math.min(merge[i], 2 * lo);          // direct swap or via lo
  }
  return total;
}
long minCost(int[] basket1, int[] basket2) {
    Map<Integer, Integer> count = new HashMap<>();   // net surplus per value
    int lo = Integer.MAX_VALUE;
    for (int x : basket1) { count.merge(x, 1, Integer::sum); lo = Math.min(lo, x); }
    for (int x : basket2) { count.merge(x, -1, Integer::sum); lo = Math.min(lo, x); }
    List<Integer> merge = new ArrayList<>();
    for (Map.Entry<Integer, Integer> e : count.entrySet()) {
        int c = e.getValue();
        if (c % 2 != 0) return -1;                   // odd total -> impossible
        for (int k = 0; k < Math.abs(c) / 2; k++) merge.add(e.getKey());
    }
    Collections.sort(merge);                         // cheapest swaps first
    long total = 0;
    for (int i = 0; i < merge.size() / 2; i++)        // pay only the cheaper half
        total += Math.min(merge.get(i), 2L * lo);     // direct swap or via lo
    return total;
}
long long minCost(vector<int>& basket1, vector<int>& basket2) {
    unordered_map<int, int> count;                  // net surplus per value
    int lo = INT_MAX;
    for (int x : basket1) { count[x]++; lo = min(lo, x); }
    for (int x : basket2) { count[x]--; lo = min(lo, x); }
    vector<int> merge;
    for (auto& [v, c] : count) {
        if (c % 2 != 0) return -1;                  // odd total -> impossible
        for (int k = 0; k < abs(c) / 2; k++) merge.push_back(v);
    }
    sort(merge.begin(), merge.end());               // cheapest swaps first
    long long total = 0;
    for (int i = 0; i < (int)merge.size() / 2; i++)  // pay only the cheaper half
        total += min((long long)merge[i], 2LL * lo); // direct swap or via lo
    return total;
}
Time: O(n log n) Space: O(n)