【贪心算法】贪心算法二

贪心算法二

  • 1.最长递增子序列
  • 2.递增的三元子序列
  • 3.最长连续递增序列

在这里插入图片描述

点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃

1.最长递增子序列

题目链接: 300. 最长递增子序列

题目分析:

在这里插入图片描述

听懂这道题一定要把动态规划里面这道题解法搞清楚,我们的贪心策略其实是基于动态规划的解法,就是动态规划的解法的过程中发现可以用贪心优化的地方。还有优选算法那里的二分查找搞清楚。我们这里的贪心策略是要用这两个东西。

算法原理:

  1. 回顾 dp 的解法

状态表示:dp[i] 表示:以 i 位置的元素为结尾的所有子序列中, 最长递增子序列的长度

状态转移方程:dp[i] = max(dp[j] + 1) (j < i && nums[j] < nums[i])

更新dp[i] 的值,就是拿着nums[i] 去前面找,当找到一个位置发现这个位置的值,nums[j] < nums[i] 说明 i 可以拼在 j 的后面,此时就用这个dp[j]也就是以 j 位置为结尾的最长递增子序列的长度 然后 + 1 更新 dp[i] 的值。当把前面都找完此时dp[i]的值就是以 i 位置的元素为结尾的所有子序列中, 最长递增子序列的长度。

最核心的操作中,我们会发现一个性质:我们在考虑最长递增子序列的 “长度” 的时候,并不关心你这个序列长什么样子,我们仅关心你的 “最后一个元素” 是谁。

  1. 贪心优化

接下来我们用一个例子模拟一下贪心过程

从前到后扫描每一个元素,当扫描第一个位置的元素时候其实我们得到一个长度为1 的序列长什么样子。(但是我们只关心递增子序列长度为x中最后一个元素,并不关心序列长什么样子),这一点在上面已经说过了。

在这里插入图片描述

扫描到3的时候发现,3是接不到7后面,所以3这个元素单独形成一个长度为1的序列,现在又找到一个长度为1的序列最后一个元素是3。此时贪心策略就来了,当我发现长度为1递增子序列有两个的时候,较大的就没有必要存了。

原因就是,所有能接到7后面的数,铁定能接到3这个数的后面,所以我们不需要存较大的7,仅需存较小的3就可以判断后面的数是否能拼到长度为1的序列后面。

这里就是我们的第一个贪心策略,存最后一个元素的时候,仅需存储最小值。

在这里插入图片描述

扫描8的时候,此时第二个贪心策略来了。我们其实有两种策略,第一种让8单独形成一个长度为1的序列,第二种要么让8拼到3的后面形成一个长度为2的序列。此时我们贪心选择第二种策略。因为要找最长递增子序列。

在这里插入图片描述

扫描到4,发现4能放到长度为1的3后面,但是不放,太浪费了,所以往下放,发现4可以自己形成一个长度为2,但是发现4小于8,所以贪心把8干掉,把4放好。

上面的过程就是,发现4能放到长度为1的3后面,但是不放。往下放,发现4能不能放到8后面,就把4放到这里,同时利用第二个贪心策略只存最小值的时候,把8干掉,4留下。

在这里插入图片描述

扫描到7,也是一样,7能拼到3后面就不放,7能拼到4后面也不放,所以7形成一个长度为3的序列

在这里插入图片描述
扫描到2,发现2拼不到3后面,只能把2放到长度为1,但是2比3小,能拼接到3后面一定能拼接到2后面,所以3干掉,保留2

在这里插入图片描述

扫描到14,发现能拼接到2,4,7后面但是都不放,所以14单独形成一个长度为4的序列

在这里插入图片描述

扫描到13,发现能拼接到2,4,7后面但是不放,不能放14后面,就放14后面,同时13比14小,14干掉,13保留

在这里插入图片描述

当整个数组扫描完,我们发现长度仅从1更新到4,所以最长递增子序列的长度就是4。

虽然这里拼接的序列并不是最终的序列,但是能统计到4,就是我们的最长递增子序列的长度。

这里我们总结一下贪心策略:

我们的贪心策略就体现在两个地方:存什么,存哪里

在这里插入图片描述

这里的贪心策略的提出就是交换论证法的思想,比如能拼接7的后面的数,铁定能拼接到3的后面,这不就是交换论证吗。

这里已经说明为什么贪心策略是对的,但是我们分析一下贪心的时间复杂度,存什么肯定是拿一个数组去存,下标为0存长度为1的最小值、下标为1存长度为2的最小值…,最耗时的就是存哪里,如果是来了一个数从前往后扫描比较时间复杂度是O(n),那整体时间复杂度还是O(N^2),这个好像和动规是一样的。那还贪心什么呢?比动规还难理解。

我们还可以发现,我们贪心得到的数组,其实还有优化的地方

  1. 利用二分优化

我们发现存长度为x的最小值数组里面的值是递增有序的。此时我们在找存哪里插入位置的时候,可以用二分快速找到插入位置。

假设来一个x,我们要找的是所有大于等于x的最小值,右边都是大于等于x,左边是小于x,这就有了二段性。就可以用二分查找了。

在这里插入图片描述

证明数组是递增的。

直接证明:

第一个元素来了直接就是一个点,第二个元素来发现能拼在第一个元素后面所以重新开一个点,如果不能放就把这个元素覆盖到原始元素,这里有个不等关系,这个元素大于前一个元素,小于后一个元素。递增是不会改变的。

在这里插入图片描述

回归一下二分,定义一个left,right,mid,如果mid落在左边 left = mid + 1,如果mid落在右边有可能是结果 right = mid,等到循环解决,left或者right就是要插入的位置。

在这里插入图片描述

这里有个细节问题,再用二分的时候要考虑边界情况,因为我们要找的是大于等于nums[i]的最小值的位置,left和right其实是在这个数组中找,有没有这个数比这个数组中所有数都大,那此时应该是数组重新开一个空间,放在这个新开位置里,所以二分之前先判断 nums[i] > ret.back(),此时不用二分,直接放在数组后一个位置。否则在二分寻找插入位置。

class Solution {
public:int lengthOfLIS(vector<int>& nums) {int n = nums.size();vector<int> ret;ret.push_back(nums[0]);for(int i = 1; i < nums.size(); ++i){if(nums[i] > ret.back()) // 如果能接在最后⼀个元素后⾯,直接放ret.push_back(nums[i]);else{// 二分插入位置int left = 0, right = ret.size() - 1;while(left < right){int mid = (left + right) / 2;if(ret[mid] < nums[i])left = mid + 1;elseright = mid;                        }ret[left] = nums[i];}}return ret.size();}
};

2.递增的三元子序列

题目链接:334. 递增的三元子序列

题目分析:

在这里插入图片描述

上面是要找到最长的递增子序列,这里仅需判断一下是否存在长度为3的递增子序列就可以了。

算法原理:

最长递增子序列有两种解法,这里也是有两种解法。

解法一:动规

利用 dp 找到数组中最长递增子序列的长度,判断是否大于等于 3 即可

时间复杂度 O(n^2),会超时的。

解法二:贪心

因为这里我们仅需判断递增子序列长度是否等于3就可以了,因此可以不用二分也是非常快的。我们只要判断长度3这里是否有值就可以了,不需要关心里面是否最小也不需要关心长度4、5、6…的情况。任意来一个x,我们仅需要比较2次,最差每个数都比较2次,总体就是2n,时间复杂度就是O(n),即使用二分也是O(log2n),差别不是很大。

在这里插入图片描述

那如何实现呢?
第一种:可以像最长递增子序列一样用数组
第二种:仅需两个变量a,b

a代表长度为1最小元素,b代表长度为2最小元素。
a初始为第一个元素,b初始为INT_MAX

在这里插入图片描述
来了一个数,先和b比较,一旦这个数大于b,说明可以放在长度3,直接返回true,如果不大于b说明是小于等于b,然后和a做比较,如果大于a说明可以放在b的位置,如果小于a说明可以放在a的位置。

在这里插入图片描述

class Solution {
public:bool increasingTriplet(vector<int>& nums) {int n = nums.size();int a = nums[0], b = INT_MAX;for(int i = 1; i < n; ++i){if(nums[i] > b) return true;else if(nums[i] > a) b = nums[i];else a = nums[i];}return false;// int n = nums.size();// vector<int> ret;// ret.push_back(nums[0]);// for(int i = 1; i < n; ++i)// {//     if(nums[i] > ret.back())//         ret.push_back(nums[i]);//     else//     {//         int left = 0, right = ret.size() - 1;//         while(left < right)//         {//             int mid = (left + right) >> 1;//             if(ret[mid] < nums[i])//                 left = mid + 1;//             else//                 right = mid;//         }//         ret[left] = nums[i];//     }// }// return ret.size() >= 3 ? true : false;}
};

3.最长连续递增序列

题目链接: 674. 最长连续递增序列

题目分析:

在这里插入图片描述

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。如果是连续的子序列其实就是子数组了,那这道题其实就变得简单了。

算法原理:

我们可以用暴力的思路来解决。用指针i固定一个数,然后再来一个指针j,让这个指针j向后移动,去找以i位置为起点的最长连续的递增序列。

怎么找?很简单,只要j位置元素比j-1位置元素大,j就往后移动,当j位置元素比j-1位置元素小就结束,此时就找完了以i位置为起点的最长连续的递增序列。

在这里插入图片描述

注意此时指针i并不直接向后移动1位,这里有一个小贪心,我们会发现 固定 i 位置然后找到这一段已经是递增并且是最长的,此时如果让i向后移动1位,那找的还是之前 i 位置的递增连续子序列,并且比之前的短,因此 i 移动到 j 位置,以 j 位起点在往后找。

在这里插入图片描述

所以我们这里的策略:贪心 + 双指针

class Solution {
public:int findLengthOfLCIS(vector<int>& nums) {int n = nums.size();int i = 0, j = 0, ret = 0;while(i < n){j = i + 1;// 找到递增区间的末端while(j < n && nums[j] > nums[j - 1]) ++j;ret = max(ret, j - i);i = j;// 直接在循环中更新下⼀个位置的起点}return ret;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/430132.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI免费UI页面生成

https://v0.dev/chat v0 - UI设计 cursor - 编写代码 参考&#xff1a;https://www.youtube.com/watch?vIyIVvAu1KZ4 界面和claude类似&#xff0c;右侧展示效果和代码 https://pagen.so/

用uniapp 及socket.io做一个简单聊天 升级 9

比这之前优化了以下功能 上线通知 群聊里适时显示在线人数 约请好友 通过好友通过socket 相应端自动变化 PC端可以拉取摄象头拍照 PC端可以录音发送 拉起摄象头发送录象 <template><view class""><scroll-view scroll-y"true" class&…

【Linux篇】常用命令及操作技巧(基础篇)

&#x1f30f;个人博客主页&#xff1a;意疏-CSDN博客 希望文章能够给到初学的你一些启发&#xff5e; 如果觉得文章对你有帮助的话&#xff0c;点赞 关注 收藏支持一下笔者吧&#xff5e; 阅读指南&#xff1a; 开篇说明帮助命令常见的七个linux操作终端实用的技巧跟文件目录…

【深入理解SpringCloud微服务】了解微服务的熔断、限流、降级,手写实现一个微服务熔断限流器

【深入理解SpringCloud微服务】了解微服务的熔断、限流、降级&#xff0c;手写实现一个微服务熔断限流器 服务雪崩熔断、限流、降级熔断降级限流 手写实现一个微服务熔断限流器架构设计代码实现整体逻辑ProtectorAspect#aroundMethod(ProceedingJoinPoint)具体实现1、获取接口对…

智慧农业——InsectMamba利用状态空间模型对害虫进行分类

介绍 论文地址&#xff1a;https://arxiv.org/abs/2404.03611 害虫分类是农业中的一个重要问题。准确识别有害害虫可减少对作物的损害&#xff0c;确保粮食安全和环境的可持续发展。然而&#xff0c;害虫及其自然环境的高度拟态性和物种多样性使得视觉特征的提取极具挑战性。…

Centos7.9 使用 Kubeadm 自动化部署 K8S 集群(一个脚本)

文章目录 一、环境准备1、硬件准备&#xff08;虚拟主机&#xff09;2、操作系统版本3、硬件配置4、网络 二、注意点1、主机命名格式2、网络插件 flannel 镜像拉取2.1、主机生成公私钥2.2、为啥有 Github 还用 Gitee2.3、将主机公钥添加到 Gitee2.3.1、复制主机上的公钥2.3.2、…

< 微积分Calculus >

微积分 微分是把整体分拆为小部分来求它怎样改变 积分是把小部分连接在一起来求整体有多大&#xff0c;可以用来求面积、体积、中点和很多其他有用的东西。 lim极限 函数f(x) -> Q(x) y&#xff1a;x变量&#xff0c;f函数&#xff0c;Q(x)函数体&#xff08;多项式&am…

【Paper Reading】结合 NanoFlow 研究,优化大语言模型服务效率的探索

作者 王伟 PAI引擎团队 近年来&#xff0c;人工智能领域的快速发展推动了大型语言模型的广泛应用&#xff0c;随之而来的是对其服务效率的迫切需求。论文《NanoFlow&#xff1a;Towards Optimal Large Language Model Serving Throughput》提出了一种突破性的新型服务框架&…

CTF 技能树 LOG -GIT泄露 笔记

log 使用虚拟机kali操作 python2 安装 apt-get install python2 进入root用户&#xff0c;下载克隆git hack库 git clone https://github.com/BugScanTeam/GitHack sudo passwd root 修改root 命名密码为root 切换登录 su root 终端进入home/kali/GitHack/ python GitH…

2024年 AI大模型我该买一张什么卡?

有钱啥也不用说&#xff0c;买张最贵的就是了。对囊中羞涩的我还说&#xff0c;我该买张什么样的显卡呢&#xff1f; 我的旧显卡RTX1060 6G&#xff0c;满负荷消耗功率110多瓦&#xff0c;几乎达到设计最大TDP&#xff0c;周日时拿了朋友的RTX3060Ti 8G&#xff0c;发现是锁算…

【中国留学网-注册_登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

手机在网状态查询接口如何用C#进行调用?

一、什么是手机在网状态查询接口&#xff1f; 手机在网状态查询接口是利用实时数据来对手机号码在运营商网络中的状态进行查询的工具&#xff0c;包括正常使用状态、停机状态、不在网状态、预销户状态等。 二、手机在网状态查询适用哪些场景&#xff1f; 例如&#xff1a;商…

Android RecyclerView 实现 GridView ,并实现点击效果及方向位置的显示

效果图 一、引入 implementation com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30 二、使用步骤 1.Adapter public class UnAdapter extends BaseQuickAdapter<UnBean.ResultBean, BaseViewHolder> {private int selectedPosition RecyclerView.NO_POSITIO…

51单片机——LED灯篇

一、LED与单片机P2管脚相连 二、点亮一个LED灯 #include <STC89C5xRC.H> void main() { P2 0xFE; //1111 1110 } P2有8个管脚&#xff0c;对应8个二进制位。 LED灯右侧接电源是正极&#xff08;1&#xff09;&#xff0c;左侧给负极&#xff08;0&#xff09;即可…

C++学习指南(六)----list

欢迎来到繁星的CSDN。本期内容主要包括&#xff0c;list的介绍、使用以及与vector的优缺点。 一、什么是list 在先前的C语言学习中&#xff0c;我们接触到了顺序表和链表&#xff0c;而在C中&#xff0c;这正好对应了vector&#xff08;动态增长顺序表&#xff09;和l…

linux第三课(linux中安装nginx与redis及SpringBoot集成redis)

目录 一.nginx引入 二.关于nginx 1.什么是nginx 2.nginx的特点 3.在nginx中安装nginx 三.关于redis 1.背景引入 2.什么是redis 3.redis的特点 4.在linux下的docker中安装redis 四.redis中的数据结构 (1)String(字符串) (2)Hash (3)list(列表) (5)zset(sorted se…

Python模拟鼠标轨迹[Python]

一.鼠标轨迹模拟简介 传统的鼠标轨迹模拟依赖于简单的数学模型&#xff0c;如直线或曲线路径。然而&#xff0c;这种方法难以捕捉到人类操作的复杂性和多样性。AI大模型的出现&#xff0c;能够通过深度学习技术&#xff0c;学习并模拟更自然的鼠标移动行为。 二.鼠标轨迹算法实…

博睿谷IT认证-订阅试学习

在这个信息爆炸的时代&#xff0c;拥有一张IT认证证书&#xff0c;就像拿到了职场晋升的通行证。博睿谷&#xff0c;作为IT认证培训的佼佼者&#xff0c;帮你轻松拿下华为、Oracle等热门认证。下面&#xff0c;让我们一起看看博睿谷如何助你一臂之力。 学习时间&#xff0c;你说…

C++入门基础知识82(实例)——实例7【 判断一个数是奇数还是偶数】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C 实例 【判断一个数是奇数还是偶数】相…

java重点学习-总结

十五 总结 https://kdocs.cn/l/crbMWc8xEZda &#xff08;总结全部的精华&#xff09; 1.面试准备 企业筛选简历规则简历编写注意事项(亮点)项目怎么找&#xff0c;学习到什么程度面试过程(表达结构、什么样的心态去找工作) 2.redis 缓存相关(缓存击穿、穿透、雪崩、缓存过期淘…