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

1.加油站

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

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

这里的diff表示gas[i]-cost[i]

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;
    }
};
相关推荐
暮雨哀尘5 分钟前
微信小程序开发:微信小程序组件应用研究
算法·微信·微信小程序·小程序·notepad++·微信公众平台·组件
dokii127 分钟前
leetcode199 二叉树的右视图
数据结构·算法·leetcode
UP_Continue40 分钟前
排序--归并排序--非递归
数据结构·算法·排序算法
花果山-马大帅42 分钟前
我的机器学习学习之路
人工智能·python·算法·机器学习·scikit-learn
坤小满学Java43 分钟前
【力扣刷题|第十七天】0-1 背包 完全背包
算法·leetcode
陈陈爱java2 小时前
Java算法模板
java·开发语言·算法
ahahahahaha23332 小时前
相似度计算 ccf-csp 2024-2-2
数据结构·c++·算法
2402_881319302 小时前
3.28学习总结
数据结构·学习·算法
夜松云2 小时前
Python数据可视化与数据处理全解析:Matplotlib图形控制与Pandas高效数据分析实战
python·算法·信息可视化·pandas·matplotlib