贪心算法(局部最优实现全局最优)第二篇

贪心算法(局部最优实现全局最优)第二篇

目录

1. LeetCode376. 摆动序列

2. LeetCode334. 递增的三元子序列

3. LeetCode674. 最长连续递增序列

4. LeetCode121. 买卖股票的最佳时机


今天我们继续来聊聊贪心算法,因为我在前面也说过贪心算法最重要的就是经验,所以我们今天继续通过刷题的方式来学习贪心算法。

1. LeetCode376. 摆动序列

这道题的意思其实也比较好理解的,就是求一个最长的摆动序列,可以从原数组中删除不符合条件的数。

这道题的话我们先来聊一下思路,因为要求的是最长的子数组。根据题目要求那么是不是说我们每次选的数字都要在有限的分为里面做到尽可能的大或者尽可能的小。为什么要这么做呢?是因为但我们选到最值的时候我们在后面的选择中才可以有更多的选择。

我们看下面这个图,里面有abcdef这几个极值点。我们看,在c和d之间有一个点x1,假设我们在这里选择了这个点的话,那么后面的数都选不了了,因为接下来是要选择比x1小的数。这也是为什么我们每一次都要选择最值的原因。

那么我们代码该怎么设计呢?我们就可以试用一个三指针,通过比较的这三个指针的大小的方式来确定极值点的位置。或者我们也可以观察一下下面这张图,以b点为例子,我们通过后面的点减去前面的点的方式,b减去ab上面的点都是正数,而bc上面的点减去b都是负数,而如果是一个非极值点的话,则都是正数,通过这样的方式我们就得到了极值点,接下来我们就使用这个方式来编写代码。

我们看下面这个代码,前面两个if条件判断都是用来特判的。同时因为原数组里面的值是可能连续好几个相同的,所以我们在这里是需要if判断的,如果相同那么就直接跳过。最后的答案之所以需要+2也是因为我们在这样判断的时候是没有加上两边的端点的,所以我们在这里需要加上。

class Solution { public: int wiggleMaxLength(vector<int>& nums) { int left=0; int right=0; int sz=nums.size(); int ret=0; if(sz==1||(sz==2&&(nums[0]==nums[1]))) return 1; if((nums[0]==nums[sz-1])&&(nums[0]==nums[sz/2])) return 1; for(int i=0;i<sz-1;++i) { right=nums[i+1]-nums[i]; if(!right) continue; if((left*right)<0) { ret++; } left=right; } return ret+2; } };

2. LeetCode334. 递增的三元子序列

这道题的话就比较简单,就是要求我们判断原数组里面有没有三个数是呈现递增关系的,有的话就返回true,没有的话就返回false。

这道题的思路其实挺好想到的,就是在代码编写的时候不要写错了就好。这道题的解法有点像我上面说的三指针。简单来说就是几个判断就好了。

可是这道题使用到了贪心吗?答案是Yes。因为我们的代码有一个思想,那就是每一次判断都在进行筛选,我们都在尽可能的让a和b变小,这样方便我们找到合适的点。

class Solution { public: bool increasingTriplet(vector<int>& nums) { int a=nums[0]; int b=INT_MAX; int sz=nums.size(); for(int i=1;i<sz;++i) { if(nums[i]>b) return true; if(a>nums[i]) a=nums[i]; else if(nums[i]!=a) b=nums[i]; else continue; } return false; } };

3. LeetCode674. 最长连续递增序列

这道题的话比较简单,就是叫我们从原数组里面找到最长的递增子数组,同时要求是连续的。

这道题的话就比较简单了,就是从头到尾遍历一遍就好,同时记录最大的ret就可以了。

class Solution { public: int findLengthOfLCIS(vector<int>& nums) { int ret=1; int ret1=1; int sz=nums.size(); for(int i=0;i<sz-1;++i) { if(nums[i+1]>nums[i]) ret1++; else ret1=1; if(ret1>ret) ret=ret1; } return ret; } };

4. LeetCode121. 买卖股票的最佳时机

这道题的话也是比较简单的,就是要求我们在原数组里面找到两数之差最大的那两个数。

所以说这道题的话我们就是通过一次遍历然后同时用一个l来不断更新最小值,这样我们就可以取到最大的数了。

这道题贪心的地方在于l一直在更新,在不断地变小。

class Solution { public: int maxProfit(vector<int>& p) { int sz=p.size(); int ret=0; int ret1=0; int l=INT_MAX;//买 for(int i=0;i<sz;++i) { if(l<p[i]) ret=max(ret,p[i]-l); if(l>p[i]) l=p[i]; } return ret; } };

Read more

【算法刷题】二叉树前中后序遍历(递归+迭代)详解

【算法刷题】二叉树前中后序遍历(递归+迭代)详解

🌈个人主页: Hygge_Code🔥热门专栏:从0开始学习Java | Linux学习| 计算机网络💫个人格言: “既然选择了远方,便不顾风雨兼程” 文章目录 * 一、二叉树的前序遍历🥝 * 1. 递归写法🍂 * 核心思路 * 步骤拆解 * 示例说明 * 代码🍋‍🟩 * 2. 迭代写法🍂 * 核心思路 * 步骤拆解 * 关键逻辑解析 * 示例说明 * 代码🍋‍🟩 * 二、二叉树的中序遍历🥝 * 1. 递归写法🍂 * 思路 * 代码🍋‍🟩 * 迭代写法🍂 * 核心思路 * 步骤拆解 * 关键逻辑解析 * 示例说明 * 代码🍋‍🟩 * 三、二叉树的后序遍历🥝 * 递归写法🍂 * 思路 * 代码🍋‍🟩 * 迭代写法1🍂🐦‍🔥 * 关键难点👏👏👏 * 解决方案 * 步骤拆解

By Ne0inhk
五大经典排序算法:插入、希尔、冒泡、选择、堆排序全攻略

五大经典排序算法:插入、希尔、冒泡、选择、堆排序全攻略

目录 --------------插入排序------------- 1、插入排序思想 2、示例代码 3、效率分析 --------------希尔排序------------- 1、希尔排序思想 2、示例代码 3、效率分析 --------------选择排序------------- 1、选择排序思想 2、示例代码 3、效率分析 ---------------堆排序-------------- 1、堆排序思想 2、示例代码 3、效率分析 --------------冒泡排序------------- 1、冒泡排序思想 2、示例代码 3、效率分析 上述五大排序性能对比: --------------插入排序------------- 1、插入排序思想 插入排序的核心思想是逐步构建有序序列: 将数组分为 “已排序” 和 “未排序” 两部分,初始时已排序部分只包含第一个元素。 每次从未排序部分取出第一个元素,将其向前插入到已排序序列中的正确位置,使得插入后的序列依然保持有序。

By Ne0inhk
【C语言】排序算法——快速排序详解(含多种变式)!!!

【C语言】排序算法——快速排序详解(含多种变式)!!!

【C语言】排序算法——快速排序详解(含多种变式)!!! * 前言 * 一 、快速排序(初阶) * 1. 视频演示 * 2. 算法思想 * 3. 实现思路 * (1)定key值 * (2)大小交换 * (3)循环 * (4)交换key * (5)分割区间 * (6)结束 * 4. 实现代码 * 二 、快速排序(中阶) * 1. 存在的问题 * 2. 优化(三数取中) * 3. 实现代码(中阶) * 三 、快速排序(高阶) * 1. 仍存在的问题 * 2. 优化(小区间优化) * 3. 实现代码(高阶)

By Ne0inhk
计算机视觉热点:三维人体姿态估计的前沿算法与论文案例

计算机视觉热点:三维人体姿态估计的前沿算法与论文案例

计算机视觉热点:三维人体姿态估计的前沿算法与论文案例 * 一、前言 * 二、三维人体姿态估计概述 * 2.1 定义与目标 * 2.2 应用场景 * 2.3 面临的挑战 * 三、前沿算法介绍 * 3.1 基于深度学习的方法 * 3.2 多视角方法 * 3.3 结合传感器的方法 * 四、算法对比与分析 * 4.1 不同算法的性能比较 * 4.2 适用场景分析 * 五、数据集介绍 * 5.1 常用数据集概述 * 5.2 数据集特点与应用 * 六、未来发展趋势 * 6.1 算法优化方向 * 6.2 新兴技术融合

By Ne0inhk