代码随想录day30|860柠檬水找零406根据身高重建队列452用最少数目的箭引爆气球|01笔记

86 阅读2分钟
  • 860柠檬水找零

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 可以根据三种不同情况进行讨论,维护零线的剩余状态。无法满足找零需求的时候停止。
  • 解题代码

  •     func lemonadeChange(bills []int) bool {
            ten, five := 0, 0
            for i := 0; i < len(bills); i++ {
                if bills[i] == 5 {
                    five++
                } else if bills[i] == 10 {
                    if five == 0 {
                        return false
                    }
                    ten++; five--
                } else {
                    if ten >= 1 && five >= 1 {
                        ten--; five--
                    } else if five >= 3 {
                        five -= 3
                    } else {
                        return false
                    }
                }
            }
            return true
        }
    
  • 406根据身高重建队列

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 首先尝试了同时讨论hi、ki值的方式进行重构,发现无法梳理出清晰的逻辑解决。
  • 然后尝试了按照ki值由小到大,相同ki则hi由大到小的顺序排列,尝试重新构建数组的过程中发现不能方便的插入。
  • 讲解观后感

  • 本题有两个维度,h和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]     // 身高按照由大到小的顺序来排
            })
        
            // 再按照K进行插入排序,优先插入K小的
        	for i, p := range people {
        		copy(people[p[1]+1 : i+1], people[p[1] : i]) //空出people[p[1]],方便后面插入
        		people[p[1]] = p
        	}
        	return people
        }
    
  • 链表
  •     // 链表实现
        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]
            })
            l := list.New()      //创建链表
            for i:=0; i < len(people); i++ {
                position := people[i][1]
                mark := l.PushBack(people[i])      //插入元素
                e := l.Front()
                for position != 0 {      //获取相对位置
                    position--
                    e = e.Next()
                }
                l.MoveBefore(mark, e)    //移动位置
                
            }
            res := [][]int{}
            for e := l.Front(); e != nil; e = e.Next() {
                res = append(res, e.Value.([]int))
            }
            return res
        }
    
  • 452 用最少数目的箭引爆气球

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 想要尝试类似跳跃游戏II的方法,当一支箭无法同时解决当前经历的气球时,然后再增加一支箭。局部贪心的思想。
  • 讲解观后感

  • 为了让气球尽可能的重叠,需要对数组进行排序。是使用贪心的必要条件。
  • 分辨是否重叠的方式就是最小右边界与当前气球左边界的关系。
  • 解题代码

  •     func findMinArrowShots(points [][]int) int {
            var res int = 1  //弓箭数
            //先按照第一位排序
            sort.Slice(points, func (i,j int) bool {
                return points[i][0] < points[j][0]
            })
        
            for i := 1; i < len(points); i++ {
                if points[i-1][1] < points[i][0] {  //如果前一位的右边界小于后一位的左边界,则一定不重合
                    res++
                } else {
                    points[i][1] = min(points[i - 1][1], points[i][1]); // 更新重叠气球最小右边界,覆盖该位置的值,留到下一步使用
                }
            }
            return res
        }
        func min(a, b int) int {
            if a > b {
                return b
            }
            return a
        }