首页 > 编程语言 > 算法随想Day32【贪心算法】| LC435-无重叠区间、LC763-划分字母区间、LC56-合并区间

算法随想Day32【贪心算法】| LC435-无重叠区间、LC763-划分字母区间、LC56-合并区间

时间:2023-03-06 09:11:32浏览次数:49  
标签:LC435 right int vector ++ 算法 intervals result 区间

LC435. 无重叠区间

贪心表现在每一步,都保证右边界尽量靠左,若两个区间出现重叠冲突,将右边界更新为两者右边界中较小的那个。

如排序后,[1,5],[2,4],[4,8],[5,6],[6,7],初始右边界为5,遇到[2,4]有冲突,+1并更新右边界为4,访问[4,8]后,right为8,遇到[5,6],跟新right为8

//return ((v1[0] == v2[0]) && (v1[1] <= v2[1]) || (v1[0] < v2[0]));

static bool cmp(vector<int>& v1, vector<int>& v2)
{
    return (v1[0] < v2[0]);
}
int eraseOverlapIntervals(vector<vector<int>>& intervals)
{
    int size = intervals.size();
    sort(intervals.begin(), intervals.end(), cmp);
    int right = intervals[0][1];
    int count = 0;
    for (int i = 1; i < size; ++i)
    {
        if (intervals[i][0] < right)
        {
            ++count;
            if (intervals[i][1] < right)
            {
                right = intervals[i][1];
            }
        }
        else
        {
            if (i < size - 1 && right > intervals[i + 1][1])
            {
                right = intervals[i + 1][0];
            }
            else
            {
                right = intervals[i][1];
            }
        }
    }
    return count;
}

LC763. 划分字母区间

自己想的方法比较简单粗暴,容器用的比较多,所以内存消耗也相应得有所增加。

开始用了unordered_map记录每个元素出现的次数,从左往右遍历中,用unordered_set记录这一段路出现的每个字符,一旦有元素的计数到0,即说明该位置有可能是这段字符串的分割点,这点的确认只需要判等(已经计数清零的字符 和 unordered_set中的个数)。

vector<int> partitionLabels(string s)
{
    vector<int> result;
    unordered_map<char, int> umap;
    unordered_set<char> used;
    for (auto it : s)
    {
        if (umap.find(it) == umap.end())
            umap.emplace(make_pair(it, 1));
        else
            ++umap[it];
    }
    int count = 0;
    int numZero = 0;
    for (auto it : s)
    {
        ++count;
        if (used.find(it) == used.end())
            used.emplace(it);
        if(--umap[it] == 0)
        {
            ++numZero;
            if (numZero == used.size())
            {
                result.emplace_back(count);
                count = 0;
                numZero = 0;
                used.clear();
            }
        }
    }
    return result;
}

Carl哥的思路和解法更加巧妙:

  • 统计每一个字符最后出现的位置
  • 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点
////Carl哥思路
vector<int> partitionLabels(string S) {
    int hash[27] = {0}; // i为字符,hash[i]为字符出现的最后位置
    for (int i = 0; i < S.size(); i++) { // 统计每一个字符最后出现的位置
        hash[S[i] - 'a'] = i;
    }
    vector<int> result;
    int left = 0;
    int right = 0;
    for (int i = 0; i < S.size(); i++) {
        right = max(right, hash[S[i] - 'a']); // 找到字符出现的最远边界
        if (i == right) {
            result.push_back(right - left + 1);
            left = i + 1;
        }
    }
    return result;
}

LC56. 合并区间

相比前面有关排序和区间的题目,这个算easy的了

static bool cmp(vector<int>& v1, vector<int>& v2)
{
    return (v1[0] < v2[0]);
}
vector<vector<int>> merge(vector<vector<int>>& intervals)
{
    vector<vector<int>> result;
    sort(intervals.begin(), intervals.end(), cmp);
    int left = intervals[0][0];
    int right = intervals[0][1];
    for (int i = 1; i < intervals.size(); ++i)
    {
        if (intervals[i][0] <= right)
        {
            if (intervals[i][1] > right)
                right = intervals[i][1];
        }
        else
        {
            result.emplace_back(vector<int>{left, right});
            left = intervals[i][0];
            right = intervals[i][1];
        }
    }
    result.emplace_back(vector<int>{left, right});
    return result;
}

标签:LC435,right,int,vector,++,算法,intervals,result,区间
From: https://www.cnblogs.com/Mingzijiang/p/17182580.html

相关文章

  • 算法时间复杂度从底到高
    O(1):常量时间,意味着算法时间并不随着数据规模而变化O(log(n)):对数时间O(n):线性时间,算法时间与数据规模成正比O(n*log(n)):拟线性时间O(n2):平方时间O(......
  • 基础算法(1)
    快速排序(O(NlogN))思路:确定分界点(序列里随机一个数都可以):左边界、右边界、中值;调整范围;递归处理左、右两段核心:每次j指针落在i指针前面位置时,将q[i]、q[j]进行swap操作(先......
  • P1220 关路灯 (有点不同的区间dp)
    P1220关路灯-洛谷|计算机科学教育新生态(luogu.com.cn)本题有个很重要的信息:大爷是可以随手关灯,所以对于区间[i~j],出于贪心,大爷最后要么在i位置,要么在j位置。......
  • 【基数排序算法详解】Java/Go/Python/JS/C不同语言实现
    说明基数排序(RadixSort)是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的......
  • 弗洛伊德算法(floyd)
    实现特点:“3个for”publicvoidfloyd(){ for(intk=0;k<vertexs.length;k++){//这个for用来取中间节点,剩下的两个for用来遍历邻接矩阵 for(inti=0;......
  • 常用数据结构和算法总结
    线性表:单链表双向链表循环链表栈队列递归字符串数组树二叉树哈夫曼树:又称为最优树,是一种带权路径长度最短的树平很二叉树B树......
  • 第2章 算法——程序的灵魂
    本文作者:FiftyOne本文链接:https://www.cnblogs.com/FiftyOne/p/17180498.html版权声明:未经作者允许严禁转载第2章 算法——程序的灵魂一个程序主要包括以下两方面的信......
  • 基于polar码和SCMA的多用户检测的联合检测译码matlab仿真,polar采用SCAN软译码,SCMA用
    1.算法描述构造的核心是通过信道极化(channelpolarization)处理,在编码侧采用方法使各个子信道呈现出不同的可靠性,当码长持续增加时,部分信道将趋向于容量近于1的完美信道(无误......
  • 手刷算法day2(1)
    104. 二叉树的最大深度 给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。说明: 叶子节点是指没有子节点的节点。示例:给......
  • k-近邻算法
    1.k-近邻算法概述简单地说,k-近邻算法采用测量不同特征值之间的距离方法进行分类优点:精度高、对异常值不敏感、无数据输入假定。缺点:计算复杂度高、空间复杂度高。适用数据范......