首页 > 编程语言 >算法学习Day36重叠区间

算法学习Day36重叠区间

时间:2024-01-21 14:56:41浏览次数:30  
标签:重叠 Day36 aps intervals int 算法 vector result 区间

Day36重叠区间

By HQWQF 2024/01/21

笔记


435. 无重叠区间

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。

注意: 可以认为区间的终点总是大于它的起点。 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。

示例 1:

  • 输入: [ [1,2], [2,3], [3,4], [1,3] ]
  • 输出: 1
  • 解释: 移除 [1,3] 后,剩下的区间没有重叠。

解法

和上一题一样,排序后遍历所有区间,并用上一个区间的右区间判断是否重叠,值得注意的是t代表的是上一个区间的右区间,在两个区间重叠时,我们应该删掉右边界更小的区间来经可能避免重复,对应代码中的t = min(t, intervals[i][1]);

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

763.划分字母区间

字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。

示例:

  • 输入:S = "ababcbacadefegdehijhklij"
  • 输出:[9,7,8] 解释: 划分结果为 "ababcbaca", "defegde", "hijhklij"。 每个字母最多出现在一个片段中。 像 "ababcbacadefegde", "hijhklij" 的划分是错误的,因为划分的片段数较少。

提示:

  • S的长度在[1, 500]之间。
  • S只包含小写字母 'a' 到 'z' 。

贪心法

统计字符串中所有字母出现的最远位置,然后遍历字符串,不断更新已经遍历到的字母的最远位置,如果这个位置与当前下标相等,说明此后不会出现已经遍历到的字母,说明这里是分割点。将长度放入解集即可。

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        if (a[0] == b[0])
            return a[1] < b[1];
        return a[0] < b[0];
    }
    vector<int> partitionLabels(string s) {
        vector<int> ap(2, -1);
        vector<vector<int>> aps;
        for (int i = 0; i < 26; i++) {
            int first = -1;
            for (int j = 0; j < s.size(); j++) {
                if (s[j] == 'a' + i) {
                    first = j;
                    break;
                }
            }
            int end = -1;
            for (int j = s.size() - 1; j >= 0; j--) {
                if (s[j] == 'a' + i) {
                    end = j;
                    break;
                }
            }
            if (first != -1) {
                vector<int> tmp = {first, end};
                aps.push_back(tmp);
            }
        }
        sort(aps.begin(), aps.end(), cmp);
        int rightBoard = aps[0][1];
        int leftBoard = 0;
        vector<int> result;
        for (int i = 1; i < aps.size(); i++) {
            if (aps[i][0] > rightBoard) {
                result.push_back(rightBoard - leftBoard + 1);
                leftBoard = aps[i][0];
            }
            rightBoard = max(rightBoard, aps[i][1]);
        }
        result.push_back(s.size() - leftBoard);
        return result;
    }
};

和上题类似的做法

直接统计所有字母存在的区间,遍历这些区间,如果区间有交集就当作一个,没有交集就加入解集。

class Solution {
public:
    static bool cmp(const vector<int>& a, const vector<int>& b) {
        if (a[0] == b[0])
            return a[1] < b[1];
        return a[0] < b[0];
    }
    vector<int> partitionLabels(string s) {
        vector<int> ap(2, -1);
        vector<vector<int>> aps;
        for (int i = 0; i < 26; i++) {
            int first = -1;
            for (int j = 0; j < s.size(); j++) {
                if (s[j] == 'a' + i) {
                    first = j;
                    break;
                }
            }
            int end = -1;
            for (int j = s.size() - 1; j >= 0; j--) {
                if (s[j] == 'a' + i) {
                    end = j;
                    break;
                }
            }
            if (first != -1) {
                vector<int> tmp = {first, end};
                aps.push_back(tmp);
            }
        }
        sort(aps.begin(), aps.end(), cmp);
        int rightBoard = aps[0][1];
        int leftBoard = 0;
        vector<int> result;
        for (int i = 1; i < aps.size(); i++) {
            if (aps[i][0] > rightBoard) {
                result.push_back(rightBoard - leftBoard + 1);
                leftBoard = aps[i][0];
            }
            rightBoard = max(rightBoard, aps[i][1]);
        }
        result.push_back(s.size() - leftBoard);
        return result;
    }
};

56.合并区间

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

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

解法

这题的不同之处在于需要进行实际的区间合并,我们倾向于添加到解集后,根据后面区间是否重叠选择修改解集的最后一个元素(合并区间)或是将区间添加进解集。

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> result;
        if (intervals.size() == 0) return result; // 区间集合为空直接返回
        // 排序的参数使用了lambda表达式
        sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b){return a[0] < b[0];});

        // 第一个区间就可以放进结果集里,后面如果重叠,在result上直接合并
        result.push_back(intervals[0]); 

        for (int i = 1; i < intervals.size(); i++) {
            if (result.back()[1] >= intervals[i][0]) { // 发现重叠区间
                // 合并区间,只更新右边界就好,因为result.back()的左边界一定是最小值,因为我们按照左边界排序的
                result.back()[1] = max(result.back()[1], intervals[i][1]); 
            } else {
                result.push_back(intervals[i]); // 区间不重叠 
            }
        }
        return result;
    }
};

标签:重叠,Day36,aps,intervals,int,算法,vector,result,区间
From: https://www.cnblogs.com/HQWQF/p/17977863

相关文章

  • floyd 算法——P1119 灾后重建
    floyd算法是图论中较为简单的最短路算法,但在某些方面远超最短路范围。算法思路定义\(f[x][y]\)为\(x\)到\(y\)节点的最短路径。初始化:若存在边\((x,y)\)则\(f[x][y]\)等于边长度;若不存在,为\(+\infty\)。特别的,\(f[x][x]=0\)。我们考虑一下,\(x,y\)这两个节点通......
  • (坚持每天写算法)算法复习与学习part1基础算法part1-11——差分
    差分和前缀和是有联系的。首先给定一个原数组a:a[1],a[2],a[3],,,,,,a[n];然后我们构造一个数组b:b[1],b[2],b[3],,,,,,b[i];使得a[i]=b[1]+b[2]+b[3]+,,,,,,+b[i]也就是说,a数组是b数组的前缀和数组,反过来我们把b数组叫做a数组的差分数......
  • 排序算法与查找
    1.排序1.1冒泡排序冒泡排序,就是将相邻两个元素进行比较,如果前面那个元素和后面那个元素进行比较,如果前面元素比后者元素大,则进行交换位置。下面举例: 由图可知,共有5个元素,进行了四轮比较,假设有n个元素,则进行n-1轮比较(外部循环)。内部元素比较变化:第一轮把最大的元素给去......
  • (坚持每天写算法)算法复习和学习part1基础算法part1-9高精度乘法
    这一道题的思路和之前都是一样的,仍然是按照算式进行模拟的,这里就直接贴代码了:#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<algorithm>usingnamespacestd;//总结:vector,size,string,size,vector[i],string[i];vector&......
  • 代码随想录算法训练营第 十 一 天| 20. 有效的括号 1047. 删除字符串中的所有相邻重
    LeetCode 20.有效的括号题目链接:20.有效的括号思路:采用栈数据结构解题;遇到左括号,压右括号入栈 LeetCode 1047.删除字符串中的所有相邻重复项题目链接:1047.删除字符串中的所有相邻重复项注意:Java中队列实现类API的使用 LeetCode 150.逆波兰表达式求值题目链......
  • 代码随想录算法训练营第十天| 232.用栈实现队列 225. 用队列实现栈
    LeetCode232.用栈实现队列题目链接:232.用栈实现队列思路:用两个栈实现队列 LeetCode  225.用队列实现栈 题目链接:225.用队列实现栈 思路:一个队列对栈进行实现(实现栈中的方法) ......
  • (坚持每天都写算法)算法复习与学习part1基础算法1.8高精度乘法
    这道知识点有点特殊,我当初在学的时候是只学了高精度*高精度,然后其他的我还没有想法,今天就来学学。有大概6天没有写新博客,主要是实习面试和期末考,实习面试没有过关,姐姐朋友推荐我先去刷一下面试题,叫我重温一下之前的知识,然后去参考一下开源项目,我决定边复习边写博客,就这样......
  • 安防视频监控汇聚平台LntonAIServer算法分析森林明烟明火算法检测
    在当今社会,随着科技的飞速发展,人工智能技术已经深入到各个领域,为人们的生活带来了极大的便利。在安防领域,人工智能技术的应用更是如虎添翼,为我们的家园提供了更加安全的保护。今天,我们就来探讨一下安防视频监控汇聚平台LntonAIServer中的森林明烟明火算法检测技术。森林火灾是一种......
  • 安防视频监控汇聚平台LntonAIServer算法分析森林明烟明火算法检测
    在当今社会,随着科技的飞速发展,人工智能技术已经深入到各个领域,为人们的生活带来了极大的便利。在安防领域,人工智能技术的应用更是如虎添翼,为我们的家园提供了更加安全的保护。今天,我们就来探讨一下安防视频监控汇聚平台LntonAIServer中的森林明烟明火算法检测技术。......
  • 视频汇聚平台LntonAIServer安防视频平台智能算法分析玩手机打电话检测算法预警
    在这个科技日新月异的时代,人工智能已经深入到我们生活的各个角落。其中,安防视频平台作为一个重要的应用领域,其智能化程度的提升,为我们的生活带来了更多的便利和安全保障。今天,我们就来聊聊LntonAIServer这个视频汇聚平台中的智能算法——玩手机打电话检测算法预警。......