【基础算法训练】——贪心

简介: 【基础算法训练】——贪心

第一题 1221. 分割平衡字符串


归纳法证明贪心


题目描述

微信图片_20221019193316.jpg解题报告


因为我不太会贪心(以前听y总讲课说贪心比较难,就战术性的逃避了贪心)。 这个题对于我而言,我首先想法的是一种模拟栈的玩法:

当扫描到R的时候,想象进栈,也就是top ++

当扫描到L的时候,想象出渣,也就是top --

当top又等于栈底(栈底规定为0吧)的时候,就是找到了一组符合要求的了


下面进入解法二,老老实实学贪心了,我现在也不会证明,先模仿宫水大大的吧,需要的友友们也可以直接看他的证明

宫水三叶の相信科学系列】归纳法证明从「最小分割点」进行分割可以得到最优解

先模拟出两种选择,一种局部最优,一种不是。


① 证明起始时(第一次分割)将「从 b 分割点将 s 断开」调整为「从 a 分割点将 s 断开」结果不会变差:

微信图片_20221019193359.jpg

① 从 b点首次分割调整为从 a 点首次分割,两种分割形式分割点两端仍为合法 LR 子串,因此不会从有解变成无解;

② 从 b 分割后的剩余部分长度小于从 a 分割后的剩余部分,同时由 b 分割后的剩余部分会被由 a 分割后的剩余部分所严格覆盖,因此「对 a 分割的剩余部分再分割所得的子串数量」至少 与「从 b 点分割的剩余部分再分割所得的子串数量」相等(不会变少)。

到这里为止,证明了对于首次分割,将任意合格分割点调整为最小分割点,结果不会变得更差(当 a < b 时还会更好)。

继续使用归纳来模拟其他剩余合格LR字串,得到的结果也是一样的,因此,就证明了只要每一次都从最小分割点进行分割,就可以得到最优解


参考代码(C++版本)

解法①——常规模拟

class Solution {
public:
    int balancedStringSplit(string s) {
        //扫一遍?
        int len = s.size();
        int top= 0,ans = 0;
        for(int i = 0; i < len;i++)
        {
            if(s[i] == 'R') top++;
            if(s[i] == 'L') top--;
            if(top == 0) ans ++;
        }
        return ans;
    }
};

解法② —— 贪心

class Solution {
public:
    int balancedStringSplit(string s) {
        int len = s.size();
        int ans = 0;
        for(int i = 0; i < len;)
        {
            //其实本质也就是我模拟的代码,只是我模拟的时候就根据生活经验来的
            int j = i+1;
            //遇到R就标记-1,遇到L就标记+1
            int flag = (s[i] == 'L' ? 1 : -1);
            while(j < len && flag != 0)
                flag += (s[j++] == 'L'? 1 : -1);
            //匹配出一组0了,也即是找到局部最优了,调整起点,统计结果
            i = j;
            ans ++;
        }
        return ans;
    }
};

第二题 1827. 最少操作使数组递增


题目描述

微信图片_20221019193557.jpg

解题报告


题目的意思是求解需要变换多少次,使数组中的每一个元素要比前一个元素大1,至于证明,现在能力微弱,后续补上吧


参考代码(C++版本)

class Solution {
public:
    int minOperations(vector<int>& nums) {
        int len = nums.size();
        int ans = 0;
        if(len == 1) return ans;
        for(int i = 1; i < len;i++)
        {
            if(nums[i-1] < nums[i]) continue;
            else 
            {
                //统计前后相邻的两个数字需要加几次1才能够实现前一个比后一个大1
                int tmp = nums[i-1] + 1 - nums[i];
                ans += tmp;
                //更新较大数字的值
                nums[i] = nums[i-1]+1;
            }
        }
        return ans;
    }
};

第三题 2144. 打折购买糖果的最小开销


题目描述

微信图片_20221019193729.jpg

解题报告


因为题目的要求是送咱的糖果只能是小于等于购买的两个糖果价格的 较小值 ,那么我们可以考虑降序排序,这种方便拿价格较大的两个糖果。

买两个,送一个,其实就可以看做是三个一组,比如拿样例来说,[3,2,1]的降序排序,买3和2 ,送1 ,那么这三个一组中,数组索引是2的糖果就送了,其他的样例也可以这种理解。

贪心的题,能够想出来吧,想证明了,还缺火候


参考代码(C++版本)

class Solution {
public:
    int minimumCost(vector<int>& cost) {
        int len = cost.size();
        int ans = 0;
        if(len == 1) return cost[0];
        if(len == 2) return cost[0]+cost[1];
        //三个一组,降序排序,拿到大的,两个,最后一个就可以送了
        sort(cost.begin(),cost.end(),greater<int>());
        for(int i = 0; i < len;i++)
            if(i % 3 == 2) continue;
            else ans += cost[i];
        return ans;
    }
};

第四题 1400. 构造 K 个回文字符串


哈希表(可用数组模拟,可用STL吧)+模拟


题目描述

微信图片_20221019193858.jpg

解题报告


这个感觉更像是一个观察规律的题吧,因为题目要咱们构造,没有让咱们找出回文串,那么难度其实就降低很多了。


首先,出现频率是偶数的字母,是一定可以形成回文串的,它怎么放都可以。

但是出现频率是奇数的字母,它是没法匹配的,所以必须放在回文串的中间。

那么对于每一个出现频率为奇数的字母,都需要单独一个回文串来容纳它。我们只要保证,题目要求构造的回文串的数目k,比出现频率为奇数的字母的个数num大。


参考代码(C++版本)

class Solution {
public:
    bool canConstruct(string s, int k) {
        int len = s.size();
        if(len < k) return false;
        if(len == k) return true;
        //这个题是让咱们构造
        //看到字符串的东西了,条件反射的去做映射吧
        int cnt[26];
        memset(cnt,0,sizeof(cnt));
        for(int i = 0; i < len;i++)
            cnt[s[i]-'a'] ++;
        int num = 0;
        for(int i = 0; i < 26;i++)
            //记录出现次数为奇数的字母
            if(cnt[i] % 2 == 1) num++;
        return num <= k;
    }
};


相关文章
|
6月前
|
算法 Java Serverless
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-444 算法训练 求和问题
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-444 算法训练 求和问题
56 1
|
6月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-439 算法训练 简单字符变换
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-439 算法训练 简单字符变换
54 1
|
1月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
蓝桥杯Python编程练习题的集合,涵盖了从基础到提高的多个算法题目及其解答。
60 3
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
|
18天前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
1月前
|
机器学习/深度学习 算法 决策智能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
【机器学习】揭秘深度学习优化算法:加速训练与提升性能
|
1月前
|
算法 Java C++
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
【贪心算法】算法训练 ALGO-1003 礼物(C/C++)
|
1月前
|
算法 C++
蓝桥 算法训练 共线(C++)
蓝桥 算法训练 共线(C++)
|
4月前
knn增强数据训练
【7月更文挑战第27天】
36 10
|
4月前
|
数据采集 编解码 人工智能
破解ChatGPT惊人耗电!DeepMind新算法训练提效13倍,能耗暴降10倍
【7月更文挑战第19天】DeepMind的JEST算法革新AI训练,提升效率13倍,节能10倍。通过联合数据批次选择,预训练指导及多分辨率训练,优化资源利用,降低能耗。实验显示性能提升,达到SOTA水平,但实施需大量资源,依赖优质参考模型。[论文链接](https://arxiv.org/pdf/2406.17711)
69 10
|
4月前
knn增强数据训练
【7月更文挑战第28天】
39 2