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

简介: 代码随想录算法训练营第三十五天 | LeetCode 435. 无重叠区间、763. 划分字母区间、56. 合并区间

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

文章链接:无重叠区间        划分字母区间        合并区间

视频链接:无重叠区间        划分字母区间        合并区间

1. LeetCode 435. 无重叠区间

1.1 思路

  1. 本题是通过删除最少个区间数使得这些区间没有重叠,注意 [1,2][2,3] 这种是不算重叠的。其实就是让我们求这些区间里有几个重叠区间,把个数统计出来然后输出即可
  2. 如何让这些区间尽可能重叠呢?通过排序。让相邻的区间挨在一起,挨个遍历时才能把重叠的区间给判断出来。那是按照左边界排序还是右边界排序呢?其实都可以,那接下来是按照左边界排序的
  3. 先判断数组长度是否为 0,为 0 直接 return 0。然后开始先对数组按照左边界排序,定义 count 计数
  4. for(int i=1;i<nums.length;i++),从 1 开始,因为要 i 和 i-1 比较。我们遍历到第 i 个区间,前一个区间是第 i-1 个,if(nums[i][0]>=nums[i-1][0])即 i 的左边界>= i-1 的右边界这种情况是不重叠的,由于挨着的不算重叠因此需要等于号,但我们要处理的是重叠区间,这里是不重叠的,因此这里不做处理
  5. else 即重叠,i 的左边界<i-1 的右边界,这里发现了重叠区间就 count++。我们这里知道了当前区间和上一个区间是重叠的了,那怎么知道下一个区间和这两个区间重不重叠呢?此时就要更新这两个区间的最小右边界,即 nums[i][1]=Math.min(nums[i][1],nums[i-1][1]),因为这个位置前面的位置一定是重叠的,而如果取了最大右边界,这两区间就不重叠了。
  6. 此时遍历到下一个区间了,这个区间为 i,拿 i 的左边界和上一个区间 i-1 更新后的右边界相比,如果 i 的左边界>=i-1 更新后的右边界,就没有重叠。如果<了就是重叠了

1.2 代码

//
class Solution {
    public int eraseOverlapIntervals(int[][] intervals) {
        Arrays.sort(intervals, (a,b)-> {
            return Integer.compare(a[0],b[0]);
        });
        int remove = 0;
        int pre = intervals[0][1];
        for(int i = 1; i < intervals.length; i++) {
            if(pre > intervals[i][0]) {
                remove++;
                pre = Math.min(pre, intervals[i][1]);
            }
            else pre = intervals[i][1];
        }
        return remove;
    }
}

2. LeetCode 763. 划分字母区间

2.1 思路

  1. 要让这个区间里的字符只出现在这个区间了,比如这个区间包含 a,其他 a 就不能出现在别的区间了
  2. 我们要统计每个字符出现过的最远位置,比如我们包含了 a,我们就要知道 a 最远出现在哪里,最远的位置之前就把当前字符出现的所有位置都包含了
  3. 整体是分为两步,一步需要记录每个元素出现的最远位置,接下来遍历的时候根据这个最远位置来决定这个区间的最远位置
  4. 首先定义个哈希数组,记录每个元素出现的最远位置,定义长度 27,因为 26 个字母,27 足够了
  5. for 循环第一次遍历数组获取哈希值,hash[s[i]-'a']=i;等于 i 是因为每次遍历更新的都是最新的下标位置。遍历结束后 hash 数组存的就是每个字符存的最远下标位置
  6. 定义个数组 result 存放结果,定义左区间和右区间的下标 left 和 right
  7. for 循环第二次遍历字符串数组,right=Math.max(right,hash[s[i]-'a']),因为我们要取的是每个字符出现的最远处,当 i 遍历到最远距离时即 i==right 就找到分割线了然后就 result 记录区间里的长度 right-left+1,更新 left=right+1。
  8. 最后 return result 即可

2.2 代码

//
class Solution {
    public List<Integer> partitionLabels(String S) {
        List<Integer> list = new LinkedList<>();
        int[] edge = new int[26];
        char[] chars = S.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            edge[chars[i] - 'a'] = i;
        }
        int idx = 0;
        int last = -1;
        for (int i = 0; i < chars.length; i++) {
            idx = Math.max(idx,edge[chars[i] - 'a']);
            if (i == idx) {
                list.add(i - last);
                last = i;
            }
        }
        return list;
    }
}

3. LeetCode 56. 合并区间

3.1 思路

  1. 本题和452. 用最少数量的箭引爆气球435. 无重叠区间很相似。把本题的区间中有重叠的都合并,最终输出所有的区间。相邻挨在一起的也要合并。
  2. 首先我们要先给数组排序,按左边界或者右边界排序都是可以的。我们就按照左边界排序
  3. 如果第 i 个区间的左边界<=第 i-1 个区间的右边界,证明这两个区间重叠了,就要合并区间了。else 就是第 i 个区间的左边界>第 i-1 个区间的右边界,就可以把第 i-1 个区间放入我们的 result 中了
  4. 首先定义个二维数组 result,如果题目给的数组长度为 0 就直接 return null。然后我们就按照左边界排序数组
  5. 由于上面已经排除了数组为 0 的情况,因此数组里肯定有一个数组,就先放入 result 中,后续如果有数组和它重叠,就把它获取然后修改
  6. for(int i=1;i<intervals.length;i++)从 1 开始是因为第 i 个和第 i-1 个比较。if(intervals[i][0]<=intervals[i-1][1])这就是重叠了,然后我们就更新新数组的边界,由于左边界一定是最小的了,因此更新的是右边界,右边界由于可能出现 i-1 的右边界比 i 的右边界还大,取的是右边界的最大值,因此就是先获取 result 的最后一个数组result.getLast(),result.getLast()[1]=Math.max(result.getLast()[1],intervals[i][1])。以上就是合并的操作,并且不需要再放入 result 中。
  7. else 就是不重叠的情况,就直接把这区间放入 result,result.add(intervals[i])

3.2 代码

//
// 版本2
class Solution {
    public int[][] merge(int[][] intervals) {
        LinkedList<int[]> res = new LinkedList<>();
        Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[0], o2[0]));
        res.add(intervals[0]);
        for (int i = 1; i < intervals.length; i++) {
            if (intervals[i][0] <= res.getLast()[1]) {
                int start = res.getLast()[0];
                int end = Math.max(intervals[i][1], res.getLast()[1]);
                res.removeLast();
                res.add(new int[]{start, end});
            }
            else {
                res.add(intervals[i]);
            }         
        }
        return res.toArray(new int[res.size()][]);
    }
}
相关文章
|
1月前
|
算法
Leetcode 初级算法 --- 数组篇
Leetcode 初级算法 --- 数组篇
38 0
|
11天前
|
存储 算法 Java
leetcode算法题-有效的括号(简单)
【11月更文挑战第5天】本文介绍了 LeetCode 上“有效的括号”这道题的解法。题目要求判断一个只包含括号字符的字符串是否有效。有效字符串需满足左括号必须用相同类型的右括号闭合,并且左括号必须以正确的顺序闭合。解题思路是使用栈数据结构,遍历字符串时将左括号压入栈中,遇到右括号时检查栈顶元素是否匹配。最后根据栈是否为空来判断字符串中的括号是否有效。示例代码包括 Python 和 Java 版本。
|
1月前
|
算法
每日一道算法题(Leetcode 20)
每日一道算法题(Leetcode 20)
23 2
|
3月前
|
人工智能 算法 Java
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
LeetCode经典算法题:井字游戏+优势洗牌+Dota2参议院java解法
50 1
|
3月前
|
存储 算法 Java
LeetCode经典算法题:预测赢家+香槟塔java解法
LeetCode经典算法题:预测赢家+香槟塔java解法
60 1
|
26天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
11天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
|
12天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。
|
13天前
|
存储 算法 决策智能
基于免疫算法的TSP问题求解matlab仿真
旅行商问题(TSP)是一个经典的组合优化问题,目标是寻找经过每个城市恰好一次并返回起点的最短回路。本文介绍了一种基于免疫算法(IA)的解决方案,该算法模拟生物免疫系统的运作机制,通过克隆选择、变异和免疫记忆等步骤,有效解决了TSP问题。程序使用MATLAB 2022a版本运行,展示了良好的优化效果。
|
12天前
|
机器学习/深度学习 算法 芯片
基于GSP工具箱的NILM算法matlab仿真
基于GSP工具箱的NILM算法Matlab仿真,利用图信号处理技术解析家庭或建筑内各电器的独立功耗。GSPBox通过图的节点、边和权重矩阵表示电气系统,实现对未知数据的有效分类。系统使用MATLAB2022a版本,通过滤波或分解技术从全局能耗信号中提取子设备的功耗信息。