题目:860. 柠檬水找零
思路:
收到钱三种情况:
- 5刀:直接收起来就可以了,不需要找钱
- 10刀:收到10刀,需要找5刀,如果没有5刀,就返回false,否则5刀-1
- 20刀:收到20刀(但是没用,找钱也不能找20所以不需要记录数量),优先考虑找10 5,因为10只能在这里用,其次再考虑找5 5 5
代码:
func lemonadeChange(bills []int) bool {
f, s := 0, 0 // 代表5 / 10 元数量
for _, x := range bills {
if x == 5 { // 收到5直接 f++
f++
}else if x == 10 { // 收到10,s++,找钱5 f--
if f == 0 { // 无法找钱
return false
}
f--
s++
}else if x == 20 { // 收到20
if s >= 1 && f >= 1 { // 优先考虑找 10 5
s--
f--
continue
}
if f >= 3 { // 其次考虑找 5 5 5
f -= 3
continue
}
return false
}
}
return true
}
参考:
题目:406. 根据身高重建队列
思路:
本题有两个维度,h和k,看到这种题目一定要想如何确定一个维度,然后再按照另一个维度重新排列。
对于本题困惑的点是先确定k还是先确定h呢,也就是究竟先按h排序呢,还是先按照k排序呢?如果按照k来从小到大排序,排完之后,会发现k的排列并不符合条件,身高也不符合条件,两个维度哪一个都没确定下来。那么按照身高h来排序呢,身高一定是从大到小排(身高相同的话则k小的站前面),让高个子在前面。
此时我们可以确定一个维度了,就是身高,前面的节点一定都比本节点高!
在这个前提下,我们从前往后插入,因为后面的元素比前面的小不会影响到前面元素的k。
代码:
func reconstructQueue(people [][]int) [][]int {
sort.Slice(people, func(i,j int) bool {
if people[i][0] == people[j][0] { // 先按照身高由大到小
return people[i][1] < people[j][1] // 在按照k由小到大
}
return people[i][0] > people[j][0]
})
// for i, x := range people {
// for j := i; j > x[1]; j-- { // 等价于下面的copy(但是copy更快一点)
// people[j] = people[j-1]
// }
// people[x[1]] = x
// }
for i, p := range people {
copy(people[p[1]+1 : i+1], people[p[1] : i]) // 空出一个位置
people[p[1]] = p
}
return people
}
参考:
题目:452. 用最少数量的箭引爆气球
思路:
这个就是给定活动时间段,找最多能做多少项活动类似;
直接按照右区间排序,然后最多能做的活动就是不重叠的区间,只需要把这几个区间都能取到,就没问题了。
代码:
func findMinArrowShots(points [][]int) int {
res := 0
right := math.MinInt
sort.Slice(points,func(i,j int)bool {
return points[i][1] < points[j][1]
})
for _, x := range points {
if x[0] > right {
right = x[1]
res++
}
}
return res
}