第八章 贪心算法 part05

合并区间

题目描述

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [start<sub>i</sub>, end<sub>i</sub>] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

解题思路

  1. 局部最优:

    • 首先,对区间按起始点进行排序,这样可以确保我们从左到右依次处理区间,并且优先处理起始点较早的区间。

    • 然后,遍历排序后的区间数组,使用一个结果数组来存储合并后的区间。

    • 在遍历过程中,检查当前区间与结果数组中最后一个区间是否有重叠:

      • 如果有重叠,则更新结果数组中最后一个区间的结束点为两个区间结束点的较大值,以合并这两个区间。
      • 如果没有重叠,直接将当前区间加入结果数组。
  2. 全局最优:

    • 通过上述局部最优的策略,我们逐步确定了每个区间的合并情况,从而在全局范围内实现了区间的最优合并。
    • 最终,我们得到了一个满足所有局部最优条件的全局最优解,即所有区间合并后的结果。

代码实现

测试地址:https://leetcode.cn/problems/merge-intervals/

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>> &intervals) {
        vector<vector<int>> result; // 存储合并后的区间
        if (intervals.size() == 0)
            return result; // 如果输入为空,直接返回空结果
        sort(intervals.begin(), intervals.end(), [](const vector<int> &a, const vector<int> &b) { return a[0] < b[0]; }); // 按区间起始点排序
        result.push_back(intervals[0]); // 将第一个区间加入结果
        for (int i = 1; i < intervals.size(); i++) {
            if (result.back()[1] >= intervals[i][0]) {
                // 如果当前区间的起始点小于等于结果中最后一个区间的结束点,说明有重叠
                result.back()[1] = max(result.back()[1], intervals[i][1]); // 合并区间,更新结束点
            }
            else {
                // 如果没有重叠,直接将当前区间加入结果
                result.push_back(intervals[i]);
            }
        }
        return result; // 返回合并后的区间
    }
};

单调递增的数字

题目描述

当且仅当每个相邻位数上的数字 xy 满足 x <= y 时,我们称这个整数是单调递增的。

给定一个整数 n ,返回 小于或等于 n 的最大数字,且数字呈 单调递增

示例 1:

输入: n = 10
输出: 9

示例 2:

输入: n = 1234
输出: 1234

示例 3:

输入: n = 332
输出: 299

解题思路

  1. 局部最优:

    • 首先,将整数转换为字符串,以便逐位处理。
    • 从后向前遍历字符串,检查每一位数字是否满足单调递增的条件。
    • 如果发现前一个数字大于当前数字,说明需要调整,将前一个数字减一,并记录当前位置作为标志位。
  2. 全局最优:

    • 通过上述局部最优的策略,我们确保了在每个局部决策中都尽可能地使数字保持单调递增。
    • 从标志位开始,将后面的所有数字设为 ‘9’,这样可以确保得到的数字是小于等于原数字的最大单调递增数字。
    • 最终,我们得到了一个满足所有局部最优条件的全局最优解,即小于等于原数字的最大单调递增数字。

代码实现

测试地址:https://leetcode.cn/problems/monotone-increasing-digits/description/

class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string strNum = to_string(n); // 将整数转换为字符串
        int flag = strNum.size(); // 初始化标志位为字符串长度
        // 从后向前遍历字符串
        for (int i = strNum.size() - 1; i > 0; i--) {
            if (strNum[i - 1] > strNum[i]) {
                // 如果前一个数字大于当前数字,说明需要调整
                flag = i; // 更新标志位
                strNum[i - 1]--; // 前一个数字减一
            }
        }
        // 从标志位开始,后面的数字全部设为 '9'
        for (int i = flag; i < strNum.size(); i++) {
            strNum[i] = '9';
        }
        return stoi(strNum); // 将字符串转换回整数并返回
    }
};
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值