代码随想录训练营第36天|LeetCode 435. 无重叠区间、763.划分字母区间、 56. 合并区间

news2024/12/26 6:17:40

参考

代码随想录

题目一:LeetCode 435.无重叠区间

怎么判断重叠

在这里插入图片描述
按照题目给出的示例,第一个区间的右边界与第二个区间的左边界重合不算重叠。对于区间问题,一般都要对区间进行排序,可以按照左边界或者右边界排序。按照个人习惯,将左边界较小的区间排在前,如果左边界相等,则右边界较小的排在前,因此对于某一个区间i和下一个区间i+1,当满足以下条件时,区间i+1和区间i重叠:

intervals[i][0] <= intervals[i+1][0] && intervals[i+1][0] < intervals[i][1]

特别注意,第一个不等式包含等号,第二个不包含等号。如果第二个等式也包含等号的话会把上图中的第二种情况也当作时重叠。如果预先对区间进行排列,保证左边界小的区间在前,那么上面的判断条件可以简化为:

intervals[i+1][0] < intervals[i][1]

怎么去重

题目中让求的是需要移除区间的最小数量,因此不需要真正的移除区间,而只要得到移除的区间个数就可以了。**如果两个有重叠,那么应该移除右边界较大的区间,保留右边界较小的区间。**因为当前区间的右边界越小,其占的区间就越小,留给下一个区间的空间就越大,重叠的可能性就越小(题目要求移除的区间数量要最小)。

代码怎么实现去重

在代码实现上不需要真正的移除区间,如果第i个区间和第i+1个区间有重叠,那么只需要将第i+1个区间的右边界更新为这两个区间右边界中较小者,这样就实现了去重操作,代码实现如下:

intervals[i+1][1] = min(intervals[i][1],intervals[i+1][1]);

经过上面的分析之后,整体的代码实现就不难了,代码如下:

class Solution {
public:
	//左边界较小的排在前,如果左边界相等,则右边界较小的排在前
    static bool cmp(vector<int>& a,vector<int>& b)
    {
        if(a[0] == b[0])    return a[1] < b[1];
        return a[0] < b[0];
    }
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        int result = 0;
        sort(intervals.begin(),intervals.end(),cmp);
        for(int i = 0; i < intervals.size()-1; i++){
            if(intervals[i+1][0] < intervals[i][1]){
                intervals[i+1][1] = min(intervals[i][1],intervals[i+1][1]);
                result++;
                cout << i << endl;
            }
        }
        return result;
    }
};

题目二:LeetCode 763.划分字母区间

题目要求两个点,分割得到尽可能多的片段和每个字母只能出现在一个片段中。如果没有“每个字母尽可能出现在一个片段中”这个限制,那无非就是每个字符作为一个片段。每个字符只能出现在一个片段中,那么当前片段中如果出现了某个字符,那么这个片段的切割点至少包含到这个字符。

怎么保证切割得到尽可能多的片段

一个片段至少一个字符,如果该字符在字符串中的其他位置还存在,那么该切割片段至少包含到该字符出现的最后位置,例如,下图中第一切割片段的第一个字符为a,则这个片段至少包含到字符a出现的最后位置处('*'表示其他小写字母),说至少是因为其他字符可能还存在在更靠后的位置。这样目前找到了一个“最靠后”的切割点,以此类推,不断寻找从下一个字符开始到切割点之间字符的最后出现位置,以此来不断更新切割点。
在这里插入图片描述
在举个例子,如下图所示,第一个字符为a,找到字符a最后出现的位置为左图中分割线前的位置,此处作为当前的分割点,下一个字符为b,字符b最后出现的位置比当前的分割位置更靠后,因此要更新切割位置,如右下图所示,接着第三个字符为c,字符c最后出现的位置在当前切割位置的前面,因此不需要更新切割位置。这样,当遍历字符到切割位置时,说明当前片段中的字符在字符串出现的位置都已经包含在该片段中,因此可以作为一个切割片段了,这样切割就能得到尽可能多的片段。
在这里插入图片描述

怎么保证每个字符只出现在一个片段中

这个问题其实已经在上面说了,要找到该字符在字符串中最后出现的位置,这样就能保证每个字符只出现在一个片段中。

找到字符最后出现的位置

这里采用哈希的思想来记录字符最后出现的位置,即预先遍历一遍字符串,然后用数组记录每个字符最后出现的位置,这样可以大大提高效率。代码实现如下:

int lastPos[26];
for(int i = 0; i < s.size(); i++)
	lastPos[s[i]-'a'] = i;

遍历一遍后,最后记录的就是每个字符最后出现的位置。
经过上面的分析之后,不难得到下面的完整代码:

class Solution {
public:
    vector<int> partitionLabels(string s) {
        vector<int> result;
        int lastPos[26];
        int start = 0, end = 0;  //分割片段的起始位置和结束位置
        for(int i = 0; i < s.size(); i++)
            lastPos[s[i]-'a'] = i;
        for(int i = 0; i < s.size(); i++){
            end = max(end,lastPos[s[i]-'a']);
            if(end == i){
                result.push_back(end+1-start);  //保存分割片段的长度
                start = end + 1;
                end = end + 1;
            } 
        }
        return result;
    }
};

题目三:LeetCode 56.合并区间

还是一样的套路,先对区间进行排序,然后再判断相邻的两个区间有没有重叠部分。按照习惯,根据左边界的值从大到小进行排序,两个区间重叠的条件就是第二个区间的右边界小于等于第一个区间的右边界,注意这里的重叠的判断和“435.无重叠区间”这题有些不同。

重叠区间的合并

在这里插入图片描述
两个重叠区间的合并:左边界取第一个区间的左边界(注意这里已经经过排序,确保第一个区间的左边界小于等于第二个区间),右边界取两个区间中的较大者。
三个及以上重叠区间的合并:每次合并两个,多次合并即可

区间排序,区间重叠的判断等之前都已经做过。
整体代码实现如下:

class Solution {
public:
    static bool cmp(vector<int>& a, vector<int>& b)
    {
        return a[0] < b[0];
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> result;
        sort(intervals.begin(),intervals.end(),cmp);
        vector<int> tmp(2);
        int index = 0;
        while(index < intervals.size()){
            tmp[0] = intervals[index][0];
            tmp[1] = intervals[index][1];
            index++;
            while(index < intervals.size() && intervals[index][0] <= tmp[1]){  //合并多个区间(也可能不用合并)
                tmp[1] = max(tmp[1],intervals[index][1]);
                index++;
            }
            result.push_back(tmp);
        }
        return result;
    }
};

上面的代码实现也不算太复杂,外层while循环遍历数组,里层while循环合并区间(也可能不用合并),用一个临时数组tmp来保存合并后的区间。看了代码随想录的代码后,将上面的代码进行优化,不使用tmp,也不需要两个while循环。初始化时将排序后的第一个区间直接加入结果数组中,然后从第一个区间开始合并,这样只需要判断当前的区间能不能和结果数组的最后一个区间合并,因为区间经过排序,能够确保相邻的区间才能够进行合并。优化后的代码实现如下:

class Solution {
public:
    static bool cmp(vector<int>& a, vector<int>& b)
    {
        return a[0] < b[0];
    }
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> result;
        sort(intervals.begin(),intervals.end(),cmp);
        result.push_back(intervals[0]);
        for(int i = 1; i < intervals.size(); i++){
            if(intervals[i][0] <= result.back()[1])
                result.back()[1] = max(result.back()[1],intervals[i][1]);
            else
                result.push_back(intervals[i]);
        }
        return result;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/51077.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计Django二手书店设计论文

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

8. 抓到Netty一个隐藏很深的内存泄露Bug | 详解Recycler对象池的精妙设计与实现

抓到Netty一个隐藏很深的内存泄露Bug | 详解Recycler对象池的精妙设计与实现 本系列Netty源码解析文章基于 4.1.56.Final版本 最近在 Review Netty 代码的时候&#xff0c;不小心用我的肉眼抓到了一个隐藏很深很深的内存泄露 Bug。 于是笔者将这个故事....哦不 .....事故&#…

介绍一款特别好用的java反编译工具jd-gui

目录 写在前面 开始 写在前面 之前用过另一款java反编译工具jad 但是这个工具有个问题就是对于一些java8的新特性&#xff0c;比如lambda表达式是解析不出来的&#xff0c;更不用说java9和java17了。关于这款工具的使用方法就不再这里赘述了&#xff0c;如果你感兴趣可以在网…

【JVM】主要组成部分及其作用

大致结构 JVM包含两个子系统和两个组件&#xff0c;两个子系统为Class loader(类装载)、 Execution engine(执行引擎)&#xff1b;两个组件为Runtime data area(运行时数据 区)、Native Interface(本地接口)。 Class loader(类装载)&#xff1a;根据给定的全限定名类名(如&…

跳槽有技巧?超强测试开发面试经验等你pick

每一次跳槽&#xff0c;相信大家都有自己的一套方法论&#xff0c;一套准备和选择过程。当然面试也是一个双向选择&#xff0c;不排除有的时候看“缘分”。不管怎么说&#xff0c;这几年来&#xff0c;在面试过大大小小挺多家公司后&#xff0c;也算职场老鸟一枚了&#xff0c;…

论文浅尝 | Hybrid Transformer Fusion for Multimodal KG Completion

笔记整理&#xff1a;陈子强&#xff0c;天津大学硕士&#xff0c;研究方向为自然语言处理论文链接&#xff1a;https://arxiv.org/pdf/2205.02357.pdf动机尽管多模态知识图谱补全较单模态知识图谱补全已经有了很大的改进&#xff0c;但仍然存在两个限制。&#xff08;1&#x…

Java内存模型与线程(1)

文章目录1. 概述2. 硬件的效率与一致性3. Java内存模型3.1 主内存与工作内存3.2 内存间交互操作并发处理的广泛应用是使得 Amdahl定律代替摩尔定律成为计算机性能发展源动力的根本原因&#xff0c;也是人类压榨计算机运算能力最有力的武器。Amdahl定律通过系统中 并行化与串行化…

MyBatis ---- MyBatis的高级查询功能

MyBatis ---- MyBatis的高级查询功能1. 查询一个实体类对象2. 查询一个list集合3. 查询单个数据4. 查询一条数据为map集合5. 查询多条数据为map集合方式一方式二1. 查询一个实体类对象 User getUserById(Param("id") int id);<!--User getUserById(Param("id…

Linux 内存虚实内存映射

Linux 内存虚实内存映射TOC 以前关于虚拟地址和物理地址的学习只是在书本上&#xff0c;今天在实际的开发板上实践了一下 代码&#xff1a; #include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/sched.h #i…

【Pandas数据处理100例】(九十一):Pandas读取txt文本文件

前言 大家好,我是阿光。 本专栏整理了《Pandas数据分析处理》,内包含了各种常见的数据处理,以及Pandas内置函数的使用方法,帮助我们快速便捷的处理表格数据。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmPandas版本:1.3.5N…

grid管理下的多实例配置不同监听端口

某现场有两个实例&#xff0c;且客户要求两个实例使用不同的端口&#xff0c;但是grid管理下的监听默认只能一个端口&#xff0c;可以通过以下方式解决 oracle下&#xff1a; srvctl add listener -l listener_cc -p 1522 -o $ORACLE_HOME srvctl add listener -l listener_…

[附源码]SSM计算机毕业设计学院竞赛管理信息系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

还不会使用 Vue-Router?请看过来

目录注明&#xff1a;路由的概念什么是路由和前端路由路由的分类配置Vue-router安装实例化router挂载配置路由一个路由匹配 多组件视图使用路由声明式路由导航 router-link编程式路由导航缓存路由组件 &#xff08;keep-alive&#xff09;注明&#xff1a; Vue-router 3.x的版本…

如何保持电机安全运行

介绍 电动机在电子系统中的使用已变得普遍。电机尺寸、控制和成本效率方面的创新使设计人员能够将电机添加到系 统中&#xff0c;从而创造新功能并扩展最终产品的功能。 随着电动机数量的急剧增加&#xff0c;对功率效率的担忧促使系统设计人员使用更高电压的电机并提高其设计…

Springboot毕业设计毕设作品,个人博客系统设计与实现

功能清单 【后台管理员功能】 系统设置&#xff1a;设置关于我们、联系我们、加入我们、法律声明 会员列表&#xff1a;查看所有注册会员信息&#xff0c;支持删除 广告管理&#xff1a;设置小程序首页轮播图广告和链接 留言列表&#xff1a;所有用户留言信息列表&#xff0c;支…

天图投资通过聆讯:资产管理规模247亿 投了小红书与奈雪

雷递网 雷建平 11月30日深圳市天图投资管理股份有限公司&#xff08;简称&#xff1a;“天图投资”&#xff09;日前通过聆讯&#xff0c;准备在港交所上市。天图投资被称为消费赛道狙击手&#xff0c;在深圳、北京、上海、香港四地设有办公室&#xff0c;投资案例包括飞鹤、周…

Python异常类

1.内建异常类的继承关系 2.常见异常汇总 异常名称 说明 ArithmeticError所有数值计算错误的基类AssertionError断言语句失败AttributeError对象没有这个属性BaseException所有异常的基类DeprecationWarning关于被弃用的特征的警告EnvironmentError操作系统错误的基类EO…

计算机组成原理-输入输出系统(持续更新中)

I/O系统基本概念 基本概念 I/O硬件 现代计算机的结构 “I/O”就是"输入/输出" IO设备就是可以将数据输入到计算机&#xff0c;或者可以接收计算机输出数据的外部设备。 常见的IO设备 主机如何与I/O设备进行交互&#xff1f; I/O接口&#xff1a;又称I/O控制器&…

11 【Express服务端渲染】

11 【Express服务端渲染】 1.Express脚手架的安装 安装Express脚手架有两种方式&#xff1a; 1.1 使用express-generator安装 使用命令行进入项目目录&#xff0c;依次执行&#xff1a; cnpm i -g express-generator可通过express -h查看命令行的指令含义 express -hUsag…

You Only Learn One Representation: Unified Network for Multiple Tasks

You Only Learn One Representation: Unified Network for Multiple Tasks一、引言&#xff08;一&#xff09;、 Explicit deep learning&#xff08;二&#xff09;、Implicit deep learning&#xff08;三&#xff09;、Knowledge modeling(四)、Kernel space alignment二、…