当前位置: 首页 > ops >正文

【贪心算法】day2

📝前言说明:

  • 本专栏主要记录本人的贪心算法学习以及LeetCode刷题记录,按专题划分
  • 每题主要记录:(1)本人解法 + 本人屎山代码;(2)优质解法 + 优质代码;(3)精益求精,更好的解法和独特的思想(如果有的话);(4)贪心策略正确性的 “证明”
  • 文章中的理解仅为个人理解。如有错误,感谢纠错

🎬个人简介:努力学习ing
📋本专栏:C++刷题专栏
📋其他专栏:C语言入门基础,python入门基础,C++学习笔记,Linux
🎀CSDN主页 愚润泽

你可以点击下方链接,进行其他贪心算法题目的学习

点击链接开始学习
贪心day1贪心day2
贪心day3贪心day4
贪心day5贪心day6
贪心day7贪心day8
贪心day9贪心day10

也可以点击下面连接,学习其他算法

点击链接开始学习
优选专题动态规划
递归、搜索与回溯贪心算法

题目

  • 179. 最大数
    • 优质解
    • 证明
  • 376. 摆动序列
    • 优质解
  • 300. 最长递增子序列
    • 优质解


179. 最大数

题目链接:https://leetcode.cn/problems/largest-number/description/
在这里插入图片描述


优质解

思路:

  • 该题其实就是一个排序问题,排序问题本质是:选择两个数,然后按规则决定两个数的先后顺序
  • 本题:对于ab,我们尝试获得 abba 的组合,哪个组合大,则为正确的排序(这就是本题的贪心策略)
  • 然后,sort的时候按我们的规则排序即可

细节:

  • 我们可以先把数字转换成字符串,然后拼接字符串,比较字典序
  • 全为 0 的特殊情况

代码:

class Solution {
public:string largestNumber(vector<int>& nums) {vector<string> strs;for(auto x: nums) strs.emplace_back(to_string(x));auto rule = [](const string& s1, const string& s2){return s1 + s2 > s2 + s1; // 返回true代表优先级高};sort(strs.begin(), strs.end(), rule);string ans = "";for(auto s: strs)ans += s;return ans[0] == '0'? string("0") : ans;}
};

时间复杂度O(k⋅nlogn)O(k⋅nlogn)O(knlogn),k 为字符串平均长度,拼接操作时间复杂度为 O(k)O(k)O(k)
空间复杂度: O(nk)O(nk)O(nk)

证明

来自Leetcode官方题解答案:
在这里插入图片描述


376. 摆动序列

题目链接:https://leetcode.cn/problems/wiggle-subsequence/description/
在这里插入图片描述


优质解

思路:

  • 贪心策略:以序列结束位置为基准,每次只考虑下一个元素是否会让此序列变得更长
  • 下一个位置有两种情况 >< ,代表两个不同状态结尾的序列
  • >up 序列的是在前一个 down 序列的长度上 +1,如果出现连续的 >,只会 +1 一次(正确性保证 1)
  • 因为我们始终记录了两种状态的序列(即:全部状态),并且每次都是在原来最优解的基础上+1,所以每次的局部最优就是全局最优

代码:

class Solution {
public:int wiggleMaxLength(vector<int>& nums) {int n = nums.size();if(n == 1) return 1;int up = 1, down = 1;for(int i = 1; i < nums.size(); i++){if(nums[i] > nums[i - 1])up = down + 1;if(nums[i] < nums[i - 1])down = up + 1;}return max(up, down);}
};

时间复杂度:O(n)O(n)O(n)
空间复杂度:O(1)O(1)O(1)


300. 最长递增子序列

题目链接:https://leetcode.cn/problems/longest-increasing-subsequence/description/
在这里插入图片描述


优质解

思路:

贪心 + 二分

  • 回想动态规划:如果新插入的数字比原来最长子序列的最后一个数字大,则可以接入(所以我们只关注子序列的最后一个元素和新插入的元素的大小)
  • end[i] 表示:长度为 i 的子序列的最后一个元素的大小
  • 每次插入数时,用二分查找找到最佳的插入位置
    • 如果可以接在目前最长的子序列后面,则代表:变得更长
    • 如果不能,则可能更新(变小)前面某一子序列的结尾的数

代码:

class Solution {
public:int lengthOfLIS(vector<int>& nums) {int n = nums.size();vector<int> end; // end[i]: 长度为 i 的序列的结尾的元素end.push_back(nums[0]);for(int i = 1; i < n; i++){if(nums[i] > end.back())end.push_back(nums[i]);else{// 二分查找int left = 0, right = end.size() - 1;while(left < right){int mid = (left + right) >> 1;if(end[mid] < nums[i])left = mid + 1;elseright = mid;}end[left] = nums[i];}} return end.size();}
};

时间复杂度:O(nlogn)O(nlogn)O(nlogn)
空间复杂度:O(n)O(n)O(n)


🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

http://www.xdnf.cn/news/18627.html

相关文章:

  • 邮箱创建时间打标与自动删除功能设计思路
  • 13种常见机器学习算法面试总结(含问题与优质回答)
  • MySQL视图有什么用?一文读懂虚拟表的六大核心价值
  • String的最大长度剖析
  • 港口集装箱编号识别误识率↓79%!陌讯多模态融合算法落地优化
  • docker 镜像问题(解决了)
  • 第二重境:视角切换——用心灵的望远镜,看见问题的全局
  • 基于 Redis + JWT 的跨系统身份共享方案
  • Vue2+Vue3前端开发笔记合集
  • 【运维进阶】case、for、while、until语句大合集
  • VSCode+Qt+CMake详细地讲解
  • 嵌入式系统bringup通用流程
  • halcon(一)一维码解码
  • 目标检测数据集 第007期-基于yolo标注格式的茶叶病害检测数据集(含免费分享)
  • MATLAB 入门:从变量定义到基础绘图的完整上手指南
  • 05-ArkUI界面开发
  • 前端漏洞(上)- CSRF漏洞
  • C++ Core Guidelines: 最佳实践与深入解析
  • .net9 解析 jwt 详解
  • Go语言 Hello World 实例
  • RabbitMQ--消费端异常处理与 Spring Retry
  • 2025最新ncm转MP3,网易云ncm转mp3格式,ncm转mp3工具!
  • ThinkPHP8学习篇(四):请求和响应
  • VSCode无权访问扩展市场
  • 【数据结构】-5- 顺序表 (下)
  • 【JavaEE】了解synchronized
  • Java 基础学习总结(211)—— Apache Commons ValidationUtils:让参数校验从 “体力活“ 变 “优雅事“
  • 电动车运行原理与最新人工智能驾驶技术在电动车上的应用展望:从基础动力系统到L5级完全自动驾驶的技术深度解析
  • 大语言模型的自动驾驶 LMDrive/DriveVLM-Dual
  • Kubernetes部署Prometheus+Grafana 监控系统NFS存储方案