代码随想录 | Day36 | 2023.09.19 |贪心05

今日题目:

435. 无重叠区间
763. 划分字母区间
56. 合并区间

今日总结

重叠区间的题目还是比较容易的,符合直觉。第一步先是考虑排序,要熟悉golang的sort.Slice写法。之后根据左右边界的大小讨论重叠与未重叠的情况,再进行内部的逻辑实现。这里的第二道题很有意思,值得研究。

435. 无重叠区间

要点

  1. 类似于之前的弓箭射气球,重叠区间的典型题目。
  2. 这道题既可以靠左排序也可以靠右排序。靠左排序就是找重叠区间靠右就是找无重叠区间。
  3. 一旦发生重叠就意味着需要删除一个区间,res++。这里面minRightBound的更新对应两种情况,一种是下一个区间的右边界小于当前minRightBound(即新区间很小,被旧区间覆盖着),另一种则是右边界大于当前minRightBound,此时不需要变。使用min函数可以省略if分支。
  4. 再加上未重叠的情况,这道题总共有三种情况。

代码:

func eraseOverlapIntervals(intervals [][]int) int {
    res := 0
    sort.Slice(intervals, func(i int, j int) bool{
        return intervals[i][0] <= intervals[j][0]
    })
    minRightBound := intervals[0][1]
    for i :=1;i<len(intervals);i++{
        if minRightBound > intervals[i][0] {
            res++
            if intervals[i][1] < minRightBound {
                minRightBound = intervals[i][1]
            }
        } else {
            minRightBound = intervals[i][1]
        }
    }
    return res
}


763. 划分字母区间

要点:

  1. 比较特殊的一道题目。一开始的想法是统计字母出现的次数,当所有遍历过的字母剩余次数归零时就分割一次字符串。想法应该没问题,不过实现起来太复杂了,放弃。
  2. 那么这道题的正确思路是先寻找每个字符最晚出现的位置。这意味着在右边不会再次出现这个字符。
  3. 当i等于遍历过的字符的最晚出现的位置,便进行一次分割。之前出现过的所有字符都不会在右边出现。所以这里right要取最大值。
func partitionLabels(s string) []int {
    res := make([]int, 0)
    hash:= make([]int, 26)
    left, right := 0, 0
    for i :=0;i<len(s);i++{
        hash[s[i]-'a'] = i
    }
    for i :=0; i <len(s);i++{
        right = max(right, hash[s[i]-'a'])
        if i == right {
            res = append(res, right - left + 1);
            left = i + 1;
        }
    }
    return res
}

func max(a int, b int) int{
    if a>b{
        return a
    }
    return b
}

56. 合并区间

要点:

  1. 类似于之前的无重叠区间,这里依然是先排序再找重叠区间。
  2. 这道题目的区别在于需要合并区间,那么只需要判断重叠时,将右边界替换为最右边界即可。
  3. 不重叠时,将之前的区间添加进结果。左边界前移,右边界也要替换为当前区间的右边界。
  4. 注意最后一个区间需要单独添加。
func merge(intervals [][]int) [][]int {
    res := [][]int{}
    sort.Slice(intervals, func(i int, j int) bool{
        if intervals[i][0] == intervals[j][0] {
            return intervals[i][1] < intervals[j][1]
        }
        return intervals[i][0] < intervals[j][0]
    })
    left, right := intervals[0][0], intervals[0][1]
    for i:=1;i <len(intervals);i++{
        if intervals[i][0] <= right {
            right = max(intervals[i][1],right)
        } else {
            res = append(res, []int{left, right})
            left = intervals[i][0]
            right = intervals[i][1]
        }
    }
    res = append(res, []int{left, right})  // 添加最后一个片段
    return res
}

func max(a int, b int) int{
    if a > b {
        return a
    }
    return b
}
//查询是否重叠,一旦出现非重叠区域:
//将最左边和最大右边界区域合并
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值