代码随想录算法训练营第三十一天

LeetCode.56 合并区间

题目链接 合并区间

题解

java 复制代码
class Solution {
    public int[][] merge(int[][] intervals) {
        List<int[]> res = new LinkedList<>();
        Arrays.sort(intervals, (x, y) -> Integer.compare(x[0], y[0]));
        for(int i = 1;i<intervals.length;i++){
            if(intervals[i][0] <= intervals[i-1][1]){
                intervals[i][0] = intervals[i-1][0];
                intervals[i][1] = Math.max(intervals[i-1][1],intervals[i][1]);
                
            }else {
                res.add(intervals[i-1]);
            }
        }
        res.add(intervals[intervals.length - 1]);
        return res.toArray(new int[res.size()][]);
    }
}

解题思路

这段代码实现了区间合并的功能,用于将重叠的区间合并为一个连续的区间。让我为你解释它的工作原理:

问题描述:给定一个区间的集合,合并所有重叠的区间,并返回合并后的区间集合。

代码采用了排序与贪心结合的策略,具体实现步骤如下:

  1. 首先对所有区间按照起始点(start)进行排序
  2. 创建一个列表res用于存储合并后的区间
  3. 遍历排序后的区间:
    • 如果当前区间的起始点小于等于前一个区间的结束点,说明两个区间重叠
      • 将当前区间的起始点更新为前一个区间的起始点
      • 将当前区间的结束点更新为两个区间结束点的最大值(合并操作)
    • 如果不重叠,则将前一个区间加入结果列表
  4. 循环结束后,将最后一个区间加入结果列表
  5. 将列表转换为数组并返回

这种方法的时间复杂度是 O (n log n),主要来自排序操作;空间复杂度是 O (n),用于存储结果。

例如,对于输入[[1,3],[2,6],[8,10],[15,18]],代码会将其合并为[[1,6],[8,10],[15,18]]

这个算法的关键在于:通过排序确保区间按起始点有序,然后通过一次遍历完成合并操作,每次遇到重叠区间就进行合并,不重叠则保存前一个区间。

LeetCode.738 单调递增的数字

题目链接 单调递增的数字

题解

java 复制代码
class Solution {
    public int monotoneIncreasingDigits(int n) {
        // 处理特殊情况
        if (n < 10) {
            return n;
        }
        
        // 将数字按位拆分,存储到列表(从低位到高位)
        List<Integer> list = new ArrayList<>();
        while (n > 0) {
            list.add(n % 10);
            n /= 10;
        }
        // 转换为数组并反转,变为从高位到低位存储
        int[] arr = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            arr[list.size() - 1 - i] = list.get(i);
        }
        
        int flag = arr.length; // 标记需要设为9的起始位置
        // 从高位向低位检查
        for (int i = arr.length - 2; i >= 0; i--) {
            if (arr[i] > arr[i + 1]) {
                arr[i]--; // 当前位减1
                flag = i + 1; // 标记后面的位置都要设为9
            }
        }
        
        // 将flag位置及之后的所有位设为9
        for (int i = flag; i < arr.length; i++) {
            arr[i] = 9;
        }
        
        // 重新组合成数字
        int res = 0;
        for (int num : arr) {
            res = res * 10 + num;
        }
        return res;
    }
}

解题思路

这段代码实现了 "单调递增的数字" 问题的解决方案,其目标是找到小于或等于给定整数 n 的最大单调递增整数(即每一位数字都大于或等于前一位数字)。

让我为你解释它的工作原理:

代码的核心思路是通过调整数字的每一位来确保其单调递增特性,具体步骤如下:

  1. 特殊情况处理:如果输入数字小于 10,直接返回该数字(单个数字本身就是单调递增的)

  2. 数字拆分与重组

    • 将数字按位拆分,先从低位到高位存储到列表
    • 转换为数组并反转,变为从高位到低位存储,便于后续处理
  3. 寻找调整位置

    • 使用 flag 标记需要设为 9 的起始位置,初始值为数组长度
    • 从高位向低位检查(实际是从数组的倒数第二位向前遍历)
    • 当发现当前位大于后一位时,说明违反了单调递增规则:
      • 将当前位减 1
      • 更新 flag 为当前位置的后一位(标记从这里开始后面的数字都要设为 9)
  4. 设置为 9 :将 flag 位置及之后的所有位都设为 9,这是为了保证得到的数字是最大可能的

  5. 重组数字:将处理后的数组重新组合成整数并返回

例如,对于输入 332

  • 拆分后得到数组 [3, 3, 2]
  • 检查发现 3 > 2(索引 1 和 2),将索引 1 的 3 减 1 变为 2,设置 flag = 2
  • flag 位置及之后设为 9,得到 [3, 2, 9]
  • 但继续检查发现 3 > 2(索引 0 和 1),将索引 0 的 3 减 1 变为 2,设置 flag = 1
  • 最终数组变为 [2, 9, 9],组合得到结果 299

这种方法的时间复杂度是 O (d),其中 d 是数字的位数;空间复杂度也是 O (d),用于存储拆分后的数字。

LeetCode.968.监控二叉树

该题目了解大概思路 还没解决

相关推荐
丶小鱼丶31 分钟前
栈算法之【有效括号】
java·算法
小徐不徐说4 小时前
每日一算:华为-批萨分配问题
数据结构·c++·算法·leetcode·华为·动态规划·后端开发
菜鸟555556 小时前
图论:最小生成树
算法·图论
2401_872945097 小时前
【补题】Codeforces Round 735 (Div. 2) C. Mikasa
算法
叫我:松哥7 小时前
基于网络爬虫的在线医疗咨询数据爬取与医疗服务分析系统,技术采用django+朴素贝叶斯算法+boostrap+echart可视化
人工智能·爬虫·python·算法·django·数据可视化·朴素贝叶斯
Star在努力7 小时前
14-C语言:第14天笔记
c语言·笔记·算法
赴3359 小时前
Numpy 库 矩阵数学运算,点积,文件读取和保存等
人工智能·算法·numpy·random·dot
自由随风飘9 小时前
机器学习-SVM支持向量机
算法·机器学习·支持向量机
屁股割了还要学10 小时前
【C语言进阶】柔性数组
c语言·开发语言·数据结构·c++·学习·算法·柔性数组
草莓熊Lotso10 小时前
【LeetCode刷题指南】--有效的括号
c语言·数据结构·其他·算法·leetcode·刷题