【发布时间】:2017-01-18 21:34:19
【问题描述】:
我一直在通过 HackerRank 测试用例学习编码考试,大部分情况下我都做得很好,但是我对一些简单的用例很感兴趣,当我看不到的时候你们都帮助我解决方案。我正在解决这个问题:
https://www.hackerrank.com/challenges/ctci-ransom-note
绑匪写了一张赎金单,但担心会被追查到他的手上。他找到了一本杂志,想知道他是否可以从里面剪下整个单词,然后用它们来制作一个无法追踪的赎金票据复制品。他笔记中的单词区分大小写,他必须使用杂志中可用的整个单词,这意味着他不能使用子字符串或串联来创建他需要的单词。
鉴于杂志上的文字和赎金信中的文字,如果他能准确地使用杂志上的整个文字复制他的赎金信,则打印 Yes;否则,打印编号。
输入格式
第一行包含两个以空格分隔的整数,分别描述(杂志中的字数)和(赎金票据中的字数)的值。 第二行包含以空格分隔的字符串,表示杂志中出现的单词。 第三行包含以空格分隔的字符串,表示赎金记录中的单词。
每个单词都由英文字母组成(即 to 和 to )。 便笺和杂志中的文字区分大小写。 输出格式
打印是,如果他可以使用该杂志创建他的赎金票据的无法追踪的复制品;否则,打印编号。
示例输入
6 4
give me one grand today night
give one grand today
样本输出
Yes
Explanation
杂志上出现了写出无法追踪的赎金记录副本所需的所有四个字,因此我们打印“是”作为我们的答案。
这是我的解决方案:
import Foundation
func main() -> String {
let v = readLine()!.components(separatedBy: " ").map{Int($0)!}
var a = [String](); var b = [String]()
if v[0] < v[1] { return "No"}
for i in 0 ..< 2 {
if i == 0 {
a = (readLine()!).components(separatedBy: " ")
} else { b = (readLine()!).components(separatedBy: " ") }
}
// Get list of elements that intersect in each array
let filtered = Set(a).intersection(Set(b))
// Map set to set of Boolean where true means set a has enough words to satisfy set b's needs
let checkB = filtered.map{ word in reduceSet(b, word: word) <= reduceSet(a, word: word) }
// If mapped set does not contain false, answer is Yes, else No
return !checkB.contains(false) ? "Yes" : "No"
}
func reduceSet(_ a: [String], word: String) -> Int {
return (a.reduce(0){ $0 + ($1 == word ? 1 : 0)})
}
print(main())
我总是在这个解决方案的 20 个测试用例中的三个上超时。因此,该解决方案似乎解决了所有测试用例,但不在其所需的时间限制内。这些都是很好的练习,但是当你被这样卡住时会非常沮丧。
我应该注意我使用了Sets 和Set(a).intersection(Set(b)),因为当我尝试映射Strings 的数组时,一半的测试用例超时。
我们将不胜感激任何更清洁或更高效的解决方案!谢谢!
【问题讨论】:
-
你能用
Foundation吗? -
是的。实际上,我总是使用它
-
你会想要查看
NSCountedSet。您需要做的就是为所有必需的字词(所需的消息)制作一个NSCountedSet,并为所有可用的字词(来自杂志)制作另一个NSCountedSet。然后只需检查每个唯一单词,第一组中的计数大于第二组中的计数 -
@Alexander - 好的,谢谢!我现在去看看
-
@pierce 将您的答案作为答案发布并接受它并不可耻。从表面上看,最好将您的解决方案添加到您的问题中。