Leetcode每日一题-1.25

难度:困难;解法:贪心

2412. 完成所有交易的初始最少钱数

给你一个下标从 0 开始的二维整数数组 transactions,其中transactions[i] = [costi, cashbacki] 。

数组描述了若干笔交易。其中每笔交易必须以 某种顺序 恰好完成一次。在任意一个时刻,你有一定数目的钱 money ,为了完成交易 i ,money >= costi 这个条件必须为真。执行交易后,你的钱数 money 变成 money - costi + cashbacki 

请你返回 任意一种 交易顺序下,你都能完成所有交易的最少钱数 money 是多少。

 

示例 1:

输入:transactions = [[2,1],[5,0],[4,2]]
输出:10
解释:
刚开始 money = 10 ,交易可以以任意顺序进行。
可以证明如果 money < 10 ,那么某些交易无法进行。

示例 2:

输入:transactions = [[3,0],[0,3]]
输出:3
解释:
- 如果交易执行的顺序是 [[3,0],[0,3]] ,完成所有交易需要的最少钱数是 3 。
- 如果交易执行的顺序是 [[0,3],[3,0]] ,完成所有交易需要的最少钱数是 0 。
所以,刚开始钱数为 3 ,任意顺序下交易都可以全部完成。

思路

我只能想到对数组进行排序,但是不知道如何排序,只是想着先按cost进行递减排序,如果cost相等,再按cashback递增排序。但是写出来答案不对。提示的思路是将原数组分为cost>cashback和cost<=cashback两个数组,然后分别排序,如果是赚钱的,则按照cost递减排序;如果是亏钱的,则按照cashback递增排序。

还有一个更好的解法——贪心:

  1. 题目要求要以任意一种交易顺序都能完成交易,那就是找出最坏情况下的交易顺序,计算这种交易顺序下需要多少初始金额

  2. 贪心的策略:

    1. 先进行亏钱的交易,最后一笔亏钱的交易是callback最大的;也就是亏钱交易中callback最大的

    2. 先进行亏钱的交易,再进行一笔成本最高的赚钱交易;也就是找出赚钱交易中cost最大的

  3. (1)(2)中选成本最大的

代码

class Solution {
    public long minimumMoney(int[][] transactions) {
        // Arrays.sort(transactions, (t1, t2)-> {
        //     //排序,将cost从大到小排,payback从小到大排序
        //     if (t1[0] == t2[0]) {
        //         return t1[1]-t2[1];
        //     } else {
        //         return t2[0]-t1[0];
        //     }
        // });
        List<int[]> cgtb=new ArrayList<>();
        List<int[]> cleb=new ArrayList<>();
        for (int[] t:transactions) {
            if (t[0] > t[1]) {
                cgtb.add(t);
            } else {
                cleb.add(t);
            }
        }
        Collections.sort(cgtb, (t1, t2)->{
            return t1[1]-t2[1];
        });
        Collections.sort(cleb, (t1, t2)-> {
            return t2[0]-t1[0];
        });


        long ans=0;
        long cur=0;
        for (int[] t : cgtb) {
            cur += t[0];
            ans = Math.max(cur, ans);
            cur -= t[1];
        }
        for (int[] t : cleb) {
            cur += t[0];
            ans = Math.max(cur, ans);
            cur -= t[1];
        }
        return ans;
    }
}
//贪心
class Solution {
    public long minimumMoney(int[][] transactions) {
        int maxCashBack = 0;
        int maxCost = 0;
        long sum = 0;
        for (int[] transaction : transactions) {
            int cost = transaction[0];
            int cashBack = transaction[1];
            if (cost > cashBack) {
                sum += cost - cashBack;
                maxCashBack = Math.max(maxCashBack, cashBack);
            } else {
                maxCost = Math.max(maxCost, cost);
            }
        }
        long ans = sum + Math.max(maxCost, maxCashBack);
        return ans;
    }
}

LICENSED UNDER CC BY-NC-SA 4.0
Comment