LeetCode 2412.完成所有交易的初始最少钱数:【年度巨献】举例说明(讲明白),由难至简(手脚不乱),附Python一行版
【LetMeFly】2412.完成所有交易的初始最少钱数:【年度巨献】举例说明(讲明白),由难至简(手脚不乱),附Python一行版
文章目录
- 【LetMeFly】2412.完成所有交易的初始最少钱数:【年度巨献】举例说明(讲明白),由难至简(手脚不乱),附Python一行版
- 问题描述
- 解题方法:贪心
- 那行,我们先选赔钱的
- 到了能赚钱时候也不容易
- 解法来了
- 写法上的优化
- 时空复杂度分析
- AC代码(简化写法)
- C++
- Python
- Java
- Go
问题描述
力扣题目链接:https://leetcode.cn/problems/minimum-money-required-before-transactions/
给你一个下标从 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 ,任意顺序下交易都可以全部完成。
提示:
1 <= transactions.length <= 105transactions[i].length == 20 <= costi, cashbacki <= 109
解题方法:贪心
“在运气和实力面前,我选择了实力”——小T如是说。
不论机遇多么坏,我都必将不负债。
那么,最“坏”的机遇是什么?当然是先亏钱( c o s t < c a s n b a c k cost \lt casnback cost<casnback)再赚钱,主打一个完事开头难。
那行,我们先选赔钱的
对于两笔赔钱投资[[6, 4], [3, 2]],有两种选择方案:
- 先选
[6, 4],那么我们需要初始资金max(6, 6 + 3 - 4) = 5 = max(6, (6 - 4) + (3 - 2) + 2) - 先选
[3, 2],那么我们需要初始资金max(3, 3 + 6 - 2) = 7 = (3 - 2) + (6 - 4) + 4
有没有发现,不论选择方案如何,初始资金都为max(cost, 赔钱总额 + 最后一次投资的cashback)。
想要初始资金最大,那么我们就最后选“cashback”最大的那次投资。
赔钱投资的最大初始资金要求为赔钱总额 + max(cashback_赔),最终剩余max(cashback_赔)开始进行赚钱投资。
到了能赚钱时候也不容易
好了,现在开始赚钱投资,钱开始越来越多了。但是,能赚钱不等于容易赚钱。想要赚钱,你得有那个资本。
既然接下来每一笔都会赚钱,也就是说每经过一笔交易所需的负担就会减小一些,所以我们不如上来就选最难的那个。
上来就选cost最大的那个,所需金额为
max(cost_赚)。
别忘了,赔钱阶段虽然赔钱,但是最终我们还剩下了max(cashback_赔)。因此还需要资金max(0, max(cashback_赔) - max(cost_赚))。
解法来了
总结:两次遍历,第一次只遍历赔钱的交易,第二次遍历不赔钱的交易。
- 对于赔钱的交易,所需初始资金
ans = 赔钱总额 + max(cashback_赔) - 对于不赔钱交易,还需初始资金加上
max(0, max(cashback_赔) - max(cost_赚))
下面先贴一个完整版代码,再放一个核心代码。
完整版代码:
/** @Author: LetMeFly* @Date: 2025-01-25 08:08:05* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-01-25 09:53:23*/
#ifdef _WIN32
#include "_[1,2]toVector.h"
#endif/*
先选赔的[[6, 4], [3, 2]]:先[6, 4]的话需要初始资金max(6, 6+3-4)=max(6, 5)=6=max(6, (6-4)+(3-2)+2)先[3, 2]的话需要初始资金max(3, 6+3-2)=max(3, 7)=7=(3-2)+(6-4)+4对于赔的:初始资金:赔钱总额+最大cashback结束资金:最大cashback
后选不赔的赚的一样:[[1, 2], [2, 3]],先[2, 3]再[1, 2]赚的不同:[[3, 5], [7, 8]]:先[3, 5]的话需要初始资金7-(5-3)=5先[7, 8]的话需要初始资金7反正就是只要钱到了最大的“cost”,钱就够了。如果先投资“cost”比较小的话,一定会赚,本金加上赚的钱达到最大cost就行,所以初始值所需较小。
*/
typedef long long ll;class Solution {
public:ll minimumMoney(vector<vector<int>>& transactions) {ll ans = 0;int M_pei = 0;// 先算赔的for (vector<int>& transaction : transactions) {if (transaction[1] < transaction[0]) {ans += transaction[0] - transaction[1];M_pei = max(M_pei, transaction[1]);}}ans += M_pei;// 再算赚的,初始资金M_peiint M_zhuan = 0;for (vector<int>& transaction : transactions) {if (transaction[1] >= transaction[0]) {M_zhuan = max(M_zhuan, transaction[0]);}}ans += max(M_zhuan - M_pei, 0);return ans;}
};#ifdef _WIN32
/*
[[2,1],[5,0],[4,2]]10
*/
/*
[[36,79],[94,94],[12,54],[71,25],[34,78],[89,66],[66,25],[7,29],[5,58],[2,25],[10,83],[62,62],[11,52],[40,5],[10,79],[74,53],[33,90],[91,81],[30,84]]270
*/// 暴力验证一个答案是否正确,复杂度O(len(t)!),对于10以内的数据还算可行
bool isok_baoliYanzheng(vector<vector<int>>& t, ll init) {sort(t.begin(), t.end());auto isok = [](vector<vector<int>>& t, ll init) {for (vector<int>& t0 : t) {if (init < t0[0]) {return false;}init += t0[1] - t0[0];}return true;};do {for (vector<int>& t0 : t) {cout << '(' << t0[0] << ", " << t0[1] << "), ";}cout << endl;bool isThisOk = isok(t, init);if (!isThisOk) {return false;}} while (next_permutation(t.begin(), t.end()));return true;
}int main() {string s;Solution sol;while (cin >> s) {vector<vector<int>> v = stringToVectorVector(s);debug(v);ll ans = sol.minimumMoney(v);dbg(ans);if (v.size() <= 10) {cout << "ifOk: ";fflush(stdout);cout << isok_baoliYanzheng(v, ans) << endl;}}return 0;
}
#endif
核心代码:
ll ans = 0;
int M_pei = 0;
// 先算赔的
for (vector<int>& transaction : transactions) {if (transaction[1] < transaction[0]) {ans += transaction[0] - transaction[1];M_pei = max(M_pei, transaction[1]);}
}
ans += M_pei;
// 再算赚的,初始资金M_pei
int M_zhuan = 0;
for (vector<int>& transaction : transactions) {if (transaction[1] >= transaction[0]) {M_zhuan = max(M_zhuan, transaction[0]);}
}
ans += max(M_zhuan - M_pei, 0);
return ans;
写法上的优化
上述代码的伪代码为:
ans = 0
M_pei = 0
for 赔钱交易 {ans += 赔钱总额M_pei = max(cashback)
}
ans += M_pei
M_zhuan = 0
for 不赔钱交易 {M_zhuan = max(cost)
}
if M_zhuan > M_pei {ans += M_zhuan - M_pei
}
我们不妨调换个顺序:
ans = 0
M_pei = 0
for 赔钱交易 {ans += 赔钱总额M_pei = max(cashback)
}
M_zhuan = 0
for 不赔钱交易 {M_zhuan = max(cost)
}
ans += M_pei // 将这一行调换到这里
if M_zhuan > M_pei {ans += M_zhuan - M_pei
}
那么,最后4行的:
ans += M_pei
if M_zhuan > M_pei {ans += M_zhuan - M_pei
}
就可以简写为:
ans += max(M_zhuan, M_pei)
同时,前面10行的:
ans = 0
M_pei = 0
for 赔钱交易 {ans += 赔钱总额M_pei = max(cashback)
}
M_zhuan = 0
for 不赔钱交易 {M_zhuan = max(cost)
}
就可以缩减为一次遍历:
ans = 0
M_pei = 0
M_zhuan = 0
for 交易 {if cost > cashback { // 赔钱ans += 赔钱总额M_pei = max(cashback)} else {M_zhuan = max(cost)}
}
不难发现,如果赔钱则cashback更小,如果不赔钱则cost更小。也就是说M_pei和M_zhuan其实都是min(cost, cashback)的最大值。
因此上述代码还可以简写为:
ans = 0
M = 0
for 交易 {ans += max(0, cost - cashback)M = max(M, min(cost, cashback))
}
也就是说:
最终答案为:赔钱总额 + 最大的“min(cost, cashback)”
时空复杂度分析
- 时间复杂度 O ( l e n ( t r a n s a c t i o n s ) ) O(len(transactions)) O(len(transactions))
- 空间复杂度 O ( 1 ) O(1) O(1)
AC代码(简化写法)
C++
/** @Author: LetMeFly* @Date: 2025-01-25 09:58:52* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-01-25 09:59:57*/
typedef long long ll;class Solution {
public:ll minimumMoney(vector<vector<int>>& transactions) {ll ans = 0;int M = 0;for (vector<int>& t : transactions) {ans += max(0, t[0] - t[1]);M = max(M, min(t[0], t[1]));}return ans + M;}
};
Python
'''
Author: LetMeFly
Date: 2025-01-25 10:00:39
LastEditors: LetMeFly.xyz
LastEditTime: 2025-01-25 10:02:46
'''
from typing import Listclass Solution:def minimumMoney(self, transactions: List[List[int]]) -> int:return sum(max(0, c - e) for c, e in transactions) + max(min(t) for t in transactions)
Java
/** @Author: LetMeFly* @Date: 2025-01-25 10:05:00* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-01-25 10:06:21*/
class Solution {public long minimumMoney(int[][] transactions) {long ans = 0;int M = 0;for (int[] t : transactions) {ans += Math.max(0, t[0] - t[1]);M = Math.max(M, Math.min(t[0], t[1]));}return ans + M;}
}
Go
/** @Author: LetMeFly* @Date: 2025-01-25 10:07:19* @LastEditors: LetMeFly.xyz* @LastEditTime: 2025-01-25 10:12:39*/
package mainfunc max_MMRBT[T int](a T, b T) T {if a > b {return a}return b
}func min_MMRBT(a int, b int) int {if a < b {return a}return b
}func minimumMoney(transactions [][]int) (ans int64) {M := 0for _, t := range transactions {ans += int64(max_MMRBT(0, t[0] - t[1]))M = max_MMRBT(M, min_MMRBT(t[0], t[1]))}ans += int64(M)return
}
同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/145352577
相关文章:
LeetCode 2412.完成所有交易的初始最少钱数:【年度巨献】举例说明(讲明白),由难至简(手脚不乱),附Python一行版
【LetMeFly】2412.完成所有交易的初始最少钱数:【年度巨献】举例说明(讲明白),由难至简(手脚不乱),附Python一行版 文章目录 【LetMeFly】2412.完成所有交易的初始最少钱数:【年度巨献】举例说明(讲明白),由难至简(手脚…...
多人-多agent协同可能会挑战维纳的反馈
在多人-多Agent协同系统中,维纳的经典反馈机制将面临新的挑战,而协同过程中的“算计”(策略性决策与协调)成为实现高效协作的核心。 1、非线性与动态性 维纳的反馈理论(尤其是在控制理论中)通常假设系统的动…...
Go学习:类型转换需注意的点 以及 类型别名
目录 1. 类型转换 2. 类型别名 1. 类型转换 在从前的学习中,知道布尔bool类型变量只有两种值true或false,C/C、Python、JAVA等编程语言中,如果将布尔类型bool变量转换为整型int变量,通常采用 “0为假,非0为真”的方…...
C语言中的局部变量和全局变量有什么区别?
在C语言中,局部变量和全局变量是两种具有不同作用域和存储期的变量。以下是它们之间的主要区别: 作用域 局部变量: 局部变量是在函数内部声明的变量。它们的作用域仅限于声明它们的函数内部。一旦函数执行完毕,局部变量就会超出…...
价值交换到底在交换什么
有人十多岁就很清醒,知道自己想要什么,要付出什么。有人20多岁清醒了,有人30多岁都不一定明白。 价值交换,四个字其实就可以解释大部分事情。价值交换和努力工作,勤劳没有任何关系。甚至努力和成功都不存在关系。 价值…...
C++传送锚点的内存寻址:内存管理
文章目录 1.C/C内存分布回顾2.C内存管理2.1 内存申请2.2 operator new与operator delete函数2.3 定位new表达式 3.关于内存管理的常见知识点3.1 malloc/free和new/delete的区别3.2 内存泄漏 希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力! 继C语…...
Prompt提示词完整案例:让chatGPT成为“书单推荐”的高手
大家好,我是老六哥,我正在共享使用AI提高工作效率的技巧。欢迎关注我,共同提高使用AI的技能,让AI成功你的个人助理。 许多人可能会跟老六哥一样,有过这样的体验:当我们遇到一个能力出众或对事物有独到见解的…...
基于django的智能停车场车辆管理深度学习车牌识别系统
完整源码项目包获取→点击文章末尾名片!...
【Proteus仿真】【51单片机】简易计算器系统设计
目录 一、主要功能 二、使用步骤 三、硬件资源 四、软件设计 五、实验现象 联系作者 一、主要功能 1、LCD1602液晶显示 2、矩阵按键 3、可以进行简单的加减乘除运算 4、最大 9999*9999 二、使用步骤 系统运行后,LCD1602显示数据,通过矩阵按键…...
洛谷P3884 [JLOI2009] 二叉树问题(详解)c++
题目链接:P3884 [JLOI2009] 二叉树问题 - 洛谷 | 计算机科学教育新生态 1.题目解析 1:从8走向6的最短路径,向根节点就是向上走,从8到1会经过三条边,向叶节点就是向下走,从1走到6需要经过两条边,…...
《Foundation 起步》
《Foundation 起步》 引言 Foundation 是一个广泛使用的开源前端框架,由 ZURB 团队创建。它旨在帮助开发者构建响应式、可访问性和移动优先的网页。本文将为您提供一个全面的指南,帮助您从零开始学习并使用 Foundation。 Foundation 简介 什么是 Foundation? Foundatio…...
【hot100】刷题记录(6)-轮转数组
题目描述: 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转…...
Android createScaledBitmap与Canvas通过RectF drawBitmap生成马赛克/高斯模糊(毛玻璃)对比,Kotlin
Android createScaledBitmap与Canvas通过RectF drawBitmap生成马赛克/高斯模糊(毛玻璃)对比,Kotlin import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.RectF …...
ThinkPad E480安装Ubuntu 18.04无线网卡驱动
个人博客地址:ThinkPad E480安装Ubuntu 18.04无线网卡驱动 | 一张假钞的真实世界 遗憾的是虽然下面的方法可以解决,但是内核升级后需要重新安装。 基本信息 Ubuntu 18.04ThinkPad E480使用下面的命令查看 Linux 内核: $ uname -r 5.0.0-3…...
自然语言处理——从原理、经典模型到应用
1. 概述 自然语言处理(Natural Language Processing,NLP)是一门借助计算机技术研究人类语言的科学,是人工智能领域的一个分支,旨在让计算机理解、生成和处理人类语言。其核心任务是将非结构化的自然语言转换为机器可以…...
Ollama 运行从 ModelScope 下载的 GGUF 格式的模型
本文系统环境 Windows 10 Ollama 0.5.7 Ollama 是什么? Ollama 可以让你快速集成和部署本地 AI 模型。它支持各种不同的 AI 模型,并允许用户通过简单的 API 进行调用 Ollama 的安装 Ollama 官网 有其下载及安装方法,非常简便 但如果希…...
Haproxy介绍及学习
一、负载均衡(load balance): 1.一种服务基于硬件设备实现的高可用反向代理技术,将特定的业务分担给指定的一个或者多个后端特定的服务器,提高了业务的并发处理能力保证业务的高可用并方便对业务后期的水平动态扩展性。 2.使用负载均衡的原因…...
【2024年华为OD机试】 (C卷,200分)- 贪心歌手(JavaScriptJava PythonC/C++)
一、问题描述 问题描述 一个歌手需要从A城前往B城参加演出,必须在T天内到达。途中会经过N座城市,且不能往回走。每两座城市之间的行程天数已知。歌手在每座城市都可以卖唱赚钱,但收入会随着停留天数的增加而递减。具体来说,第一…...
深度学习在金融风控中的应用:突破传统模型的瓶颈
深度学习在金融风控中的应用:突破传统模型的瓶颈 金融风险控制(简称“风控”)是现代金融体系中至关重要的一环,关系到金融机构的稳定性、客户的安全以及整体经济的健康运行。近年来,随着深度学习的迅猛发展,传统的风控模型正面临被颠覆的挑战,新的技术手段和思维方式正…...
LLM - 大模型 ScallingLaws 的指导模型设计与实验环境(PLM) 教程(4)
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/145323420 免责声明:本文来源于个人知识与公开资料,仅用于学术交流,欢迎讨论,不支持转载。 Scaling Laws (缩放法则) 是大模型领域中,用于描述 模型性能(Loss) 与…...
从零构建开源ADAS原型:车道检测、目标识别与PID控制实践
1. 项目概述:从零到一,构建一个开源的ADAS原型系统 最近几年,汽车行业最火的话题之一就是“智能驾驶”。无论是传统车企还是新势力,都在宣传自家的辅助驾驶功能,什么自适应巡航、车道保持、自动紧急制动,听…...
政务知识图谱 + 大模型:打造可解释、可信任 AI
在数字政务加速迈向智能化的今天,AI 技术已深度渗透到政务服务、社会治理、机关办公等各个场景,从智能问答、政策解读到辅助决策、风险预警,AI 正在成为提升政务效能、优化服务体验的核心力量。但与此同时,传统 AI 技术在政务领域…...
基于USB HID与CircuitPython的交互式硬件开发实战
1. 项目概述:一个需要你“手摇发电”才能保持屏幕亮度的硬件装置如果你觉得每天盯着手机屏幕的时间太长,想找个物理方式来“惩罚”一下自己的拖延症,或者单纯想体验一下用硬件直接“操控”手机的感觉,那么这个项目正对你的胃口。这…...
全栈代码资源聚合库:开发者如何高效利用开源代码示例提升工程能力
1. 项目概述:一个面向开发者的全栈代码资源聚合库最近在GitHub上看到一个挺有意思的项目,叫wuwangzhang1216/claude-code-source-all-in-one。光看这个名字,你大概能猜到这是个什么——没错,这是一个围绕“代码”和“源代码”做文…...
告别GBIF官网卡顿!用R语言raster/dismo包5分钟搞定物种分布数据下载与清洗
告别GBIF官网卡顿!用R语言raster/dismo包5分钟搞定物种分布数据下载与清洗 当你在深夜赶论文,急需下载某个物种的全球分布数据时,GBIF官网却不断弹出"503 Service Unavailable";当你终于打开页面,却发现每页…...
嵌入式Linux驱动DLP投影:硬件接口、软件栈与实战应用
1. 项目概述:当DLP投影遇上嵌入式Linux如果你正在寻找一个既能玩转嵌入式Linux,又能探索前沿投影显示技术的项目,那么DLP LightCrafter™ Display 2000评估模块(EVM)绝对是一个让你眼前一亮的平台。它不是一个简单的投…...
老旧主板救星记:手把手教你诊断华硕H81M-CT的USB过流保护故障
老旧主板救星记:手把手教你诊断华硕H81M-CT的USB过流保护故障 当陪伴多年的老电脑突然开始"闹脾气",每次开机15秒就自动关机,屏幕上还跳出"USB Device over current status Detected"的警告时,先别急着把它送…...
人为什么要活着的庖丁解牛
它的本质是:**这个问题本身是一个 逻辑陷阱 (Logical Trap)。它预设了生命必须有一个 外部赋予的、预先定义的“目的” (Pre-defined Purpose),就像软件必须有“需求文档”一样。然而,宇宙是 无目的的 (Purposeless),生命是 涌现的…...
Wwise音频文件处理终极指南:3步完成游戏音效解包与替换
Wwise音频文件处理终极指南:3步完成游戏音效解包与替换 【免费下载链接】wwiseutil Tools for unpacking and modifying Wwise SoundBank and File Package files. 项目地址: https://gitcode.com/gh_mirrors/ww/wwiseutil 还在为游戏音频文件无法编辑而烦恼…...
9.9元ESP32-C3移植RT-Thread Nano:低成本RTOS开发与调试实战
1. 项目概述:当开源RTOS遇上性价比神板最近在捣鼓嵌入式开发,发现了一块宝藏开发板——ESP32-C3的某个简约款,价格直接干到了9.9元。这个价格,别说喝杯奶茶了,连个像样的模块都买不到,但它不仅能跑起来&…...
