如果你在PAT甲级考场上拿到这套题,翻到Find Coins这一题时,第一反应多半是:这不就是"两数之和"吗?但等你交上去,迎接你的可能不是AC,而是TLE或者WA。这道25分的题,放在整套卷子里不算难,却是每年栽跟头人数最多的题之一。我见过太多考生在它上面浪费时间,原因无非两个:要么想都没想直接双重循环,要么根本没读懂题干里藏着的那句"If there are many solutions, you must output the one with the minimum a"意味着什么。
这篇文章我会把这道Find Coins的完整解法、考场上的思考路径、以及我当时踩过的坑全部拆开讲清楚。不管你是刚开始刷PAT甲级的新手,还是已经刷到中期想补漏的老手,这篇文章都能让你少走弯路。
1. 题目到底在问什么:不只是一句"找两枚硬币"
PAT的题目描述通常很简洁,但越简洁的题,越喜欢在边界条件上埋雷。Find Coins就是典型代表,原题大意是这样:
Eva has a bunch of coins. She wants to pay exact amount M with two coins. Given all the coin values, you are supposed to tell her if she can find two coins that sum up to M. If there are many solutions, output the one with the minimum a. It is guaranteed that all the coin values are positive integers.
翻译成人话就是:给你一堆硬币,每个硬币有面值,问能不能找到两枚硬币,让它们面值加起来正好等于M。如果有多种组合,输出"第一枚硬币面值最小"的那组。注意,这里说的"第一枚"不是输入顺序,而是面值最小。
1.1 描述信息量最大的几个字
很多人栽就栽在"两枚"这个词上。两枚硬币意味着什么?意味着你不能拿同一枚硬币当两次用。举个例子,如果M是10,硬币里恰好只有一个面值为5的硬币,你能输出"5 5"吗?不能。因为根本不存在第二枚5。但如果你有两个面值为5的硬币,那就可以。
这个细节在英文题干中只体现为"two coins",读题快的人很容易顺手忽略。等到写哈希表版本的时候,如果你用了不记录次数的set,就会在这里翻车。
1.2 输入输出格式的隐含约束
输入第一行给两个正整数N和M,N是硬币数量,M是目标金额。第二行给出N个硬币的面值。输出格式有讲究:如果存在解,输出两个面值a和b,a ≤ b,并且a尽可能小;如果无解,输出一个固定字符串"No Solution"。
这里有个容易忽略的点:题目原题并没有说明硬币面值的上限。我印象中数据范围里硬币面值通常不超过500,但M却可能到1000。也就是说,你不能理所当然地认为"面值一定比M小",虽然如果面值大于M,它不可能出现在解里,但你不做剪枝也不会出错,只是浪费时间。
1.3 样例会说话
我们来看一个标准样例:
code复制输入:
8 15
1 2 8 7 2 4 11 15
输出:
4 11
为什么不是"7 8"?因为7+8=15也是合法解。但题目要求输出a最小的那组,4比7小,所以要输出"4 11"。如果只有一个解,那就无所谓。这个样例其实就是在暗示:你的算法必须能处理"多解取最小a"。
还有一组常见边界样例:
code复制输入:
7 14
1 8 7 2 4 11 15
输出:
No Solution
你看,1+15=16,8+7=15,2+4=6,7+11=18,没有一个组合等于14,那就要老老实实输出No Solution。注意,这个字符串大小写一个
