/*
难度:中等
夏日炎炎,小男孩Tony想买一些雪糕消消暑。
商店中新到n支雪糕,用长度为n的数组costs表示雪糕的定价,其中costs[i]表示第i支雪糕的现金价格。
Tony一共有coins现金可以用于消费,他想要买尽可能多的雪糕。
请计算Tony可以买到的雪糕的最大数量。
Tony可以按任意顺序购买雪糕。
示例:
输入:costs=[1,3,2,4,1], coins=7
输出:4
示例:
输入:costs=[10,6,8,7,7,8], coins=5
输出:0
示例:
输入:costs=[1,6,3,1,2,5], coins=20
输出:6
提示:
costs.length == n
1 <= n <= 10^5
1 <= costs[i] <= 10^5
1 <= coins <= 10^8
*/
extension Daily {
static func test_leetcode1833() {
let cases = [
([1,3,2,4,1], 7),
([10,6,8,7,7,8], 5),
([1,6,3,1,2,5], 20)
]
for (costs, coins) in cases {
// let res = Daily.leetcode1833(costs: costs, coins: coins)
let res = Daily.leetcode1833(costs: costs, coins: coins)
// print("最终结果 \(res)")
}
}
//1 用map计数后再排序,可以减少重复价格雪糕的排序
//还有一种类似的方法: 因为1<=costs[i]<=10^5,所以可以直接统计从1到10^5出现的次数,而不需要用map,效率更高
static func leetcode1833(costs: [Int], coins:Int) -> Int {
if costs.count < 1 || coins < 1 {
return 0
}
var map: [Int:Int] = [Int:Int]()
for acost in costs {
map[acost] = (map[acost] ?? 0) + 1
}
let sorted = map.sorted{ $0.key < $1.key}
// print("sorted: \(sorted)")
var sum = 0
var total = 0
var rest = coins
for idx in 0..<sorted.count {
let key = sorted[idx].key
if rest < key {
break
}
let canby = rest / key
let available = sorted[idx].value
if available > canby {
total += canby
sum += canby*key
break
}
let xcost = available * key
total += available
sum += xcost
rest -= xcost
}
// print("coins消耗:\(sum), 能买 \(total) 支雪糕 \n")
return total
}
//2 将costs从小到大排序,然后累加并与coins比较;缺点是排序会比较耗时
static func leetcode1833_2(costs: [Int], coins:Int) -> Int {
if costs.count < 1 || coins < 1 {
return 0
}
let sorted = costs.sorted()
// print("sorted: \(sorted)")
var sum = 0
var total = 0
for idx in 0..<sorted.count {
if sum + sorted[idx] <= coins {
sum += sorted[idx]
total += 1
}
else {
break
}
}
// print("coins消耗:\(sum), 能买 \(total) 支雪糕 \n")
return total
}
//3 动态规划,但是如果map较大,则此方法不适用
static func leetcode1833_3(costs: [Int], coins:Int) -> Int {
if costs.count < 1 || coins < 1 {
return 0
}
let cols = coins + 1
let rows = costs.count + 1
var map = Array(repeating: 0, count: rows * cols );
for row in 1..<rows {
let current = costs[row-1]
for col in 1..<cols {
let idx = row*cols + col
let topidx = idx - cols
if current > col {
map[idx] = map[topidx]
}
else if current == col {
if map[topidx] < 1 {
map[idx] = 1
}
}
else {
let include = map[row*cols + col - current - cols] + 1
if include > map[topidx] {
map[idx] = include
}
}
}
}
showMap(map: map, options: costs, rows: rows, cols: cols)
print(" 能买 \(map[rows*cols - 1]) 支雪糕 \n")
// print("coins消耗:\(sum), 能买 \(total) 支雪糕 \n")
return map[rows*cols - 1]
}
}
04-18
809
04-24
394