[贪心算法] 加油站 && 单调递增的数字 && 坏了的计算器 && 合并区间 && 无重叠区间

1.加油站

暴力解法:两层for循环,(先写一下,优化版本就是根据暴力解法写出来的)

优化:当从a位置出发到f位置的时候发现油变成负数了,那就说明从a位置到f位置这个区间内,所有的点都无法到达 ,所以我们直接从f的下一个位置开始出发寻找,这样时间复杂度就变低了(贪心

这里的diff表示gasi-costi

cpp 复制代码
class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int n=gas.size();
        for(int i=0;i<n;i++)
        {
            int total=0,step=0;
            for(step=0;step<n;step++)
            {
                int index=(i+step)%n;
                total=total+gas[index]-cost[index];
                if(total<0)  break;
            }
            if(total>=0) return i;
            i+=step;
        }
        return -1;
    }
};

2.单调递增的数字

暴力:同样用两层for循环即可

优化:

我们只需要把数字成变小趋势的前一个数字-1,后面的数据全改成9即可;

但是要注意,当成变小趋势的前一个数字不止一个的时候,就要把最前面的数字-1,

cpp 复制代码
class Solution {
public:
    int monotoneIncreasingDigits(int n) {
        string num=to_string(n);
        int size=num.size();
        int i=0;
        //找到第一个变化的数字
        while(i+1<size() && num[i]<=num[i+1])
            i++;
        if(i+1==size)   return n;//说明这个数就是递增的
        //找到第一位
        while(i-1>=0 &7 num[i]==num[i-1])
            i--;

        //该数值
        s[i]--;
        for(int j=i+1;j<n;j++)
        {
            s[j]='9';
        }
        return stoi(num);
    }
};

3.坏了的计算器

cpp 复制代码
> 正向求解:贪心:如果小于目标值就*2,大于目标值就--; 举个例子5->8
> 先*2变成10,在--两次变成8需要三次操作,但是最优操作只需要两次,所以这个贪心是错误的。
> 根据正难则反,我们可以去反推,用target->startValue;那操作条件就变成了只能 进行÷2和++;
> 因为整数的除法是向下取整的,所以碰到奇数的只能进行++操作; 分类讨论 当target>startValue 奇数偶数都是++
> 当target<startValue 奇数++ 偶数/2
cpp 复制代码
class Solution {
public:
    int brokenCalc(int startValue, int target) {
        int ret=0;
        while(target>startValue)
        {
            if(target%2==0) target/=2;
            else    target+=1;
            ret++;
        }
        return ret+startValue-target;
    }
};

4.合并区间

合并区间: 把第一个位置的数设为left和right 要比较的数字左右两边设为a和b

如果有重叠部分:right>=a,那就把区间变成left,max(right,b)

如果没有重叠部分,直接把当前的数组加入到数组中,然后把left和right设置位置从a和b开始向后出发

cpp 复制代码
class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {

        //1.排序
        sort(intervals.begin(),intervals.end());

        //合并
        int left=intervals[0][0],right=intervals[0][1];
        vector<vector<int>> ret;
        for(int i=1;i<intervals.size();i++)
        {
            int a=intervals[i][0],b=intervals[i][1];
            if(right>=a)//有重叠部分
            {
                //求并集
                right=max(right,b);
            }
            else
            {
                ret.push_back({left,right});
                left=a;
                right=b;
            }
        }
        //把最后一次也添加到里面
        ret.push_back({left,right});
        return ret;
    }
};

5.无重叠区间

和上题类似,但是这题的left我们不需要关注 如果有重叠right>a,就把右端点较大的值移除 如果没有重叠,right=b,继续向后出发

cpp 复制代码
class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        
        //1.排序
        sort(intervals.begin(),intervals.end());
        int left=intervals[0][0],right=intervals[0][1];
        int ret=0;
        //删除区间
        for(int i=1;i<intervals.size();i++)
        {
            int a=intervals[i][0],b=intervals[i][1];
            if(right>a)//有重复区间
            {
                //贪心:删除右端点大的区间
                right=min(right,b);
                ret++;
            }
            else
            {
                left=a;
                right=b;
            }
        }
        return ret;
    }
};
相关推荐
akunkuntaimei12 分钟前
2026年高考数学各省真题及答案(完整版)
算法·高考
Hello:CodeWorld1 小时前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法
8Qi82 小时前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
youngerwang3 小时前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
KaMeidebaby4 小时前
卡梅德生物技术快报|纯化重组蛋白实操详解
人工智能·python·tcp/ip·算法·机器学习
手写码匠4 小时前
从零实现 Prompt 工程引擎:结构化提示、自动优化与多轮自省体系
人工智能·深度学习·算法·aigc
无限码力5 小时前
阿里算法岗 0530笔试真题 - 多约束条件下的元素匹配统计
算法·阿里笔试真题·阿里机试真题·阿里算法岗笔试
lqqjuly5 小时前
MLA — 多头潜在注意力深度解析
深度学习·神经网络·算法
吴可可1235 小时前
SolidWorks草图转三维DWG技巧
算法
redaijufeng6 小时前
C++雾中风景7:闭包
c++·算法·风景