【贪心算法】No.1---贪心算法(1)

news/2024/11/8 4:46:49 标签: 贪心算法, 算法

文章目录

  • 前言
  • 一、算法>贪心算法
  • 二、算法>贪心算法示例:
    • 1.1 柠檬⽔找零
    • 1.2 将数组和减半的最少操作次数
    • 1.3 最⼤数
    • 1.4 摆动序列
    • 1.5 最⻓递增⼦序列
    • 1.6 递增的三元⼦序列


前言

在这里插入图片描述

👧个人主页:@小沈YO.
😚小编介绍:欢迎来到我的乱七八糟小星球🌝
📋专栏:算法>贪心算法
🔑本章内容:算法>贪心算法
记得 评论📝 +点赞👍 +收藏😽 +关注💞哦~


一、算法>贪心算法

算法>贪心算法是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法算法>贪心算法解决问题的过程中,每一步都做出一个看似最优的决策,这个决策依赖于当前问题状态,不依赖于解决问题的前面的步骤和将来的步骤。这种方法在很多情况下并不会得到最优解,但是在某些问题上算法>贪心算法的解就是最优解。

二、算法>贪心算法示例:

1.1 柠檬⽔找零

  1. 题⽬链接:860. 柠檬⽔找零
  2. 题⽬描述
    在这里插入图片描述
  3. 解法(贪⼼):
    贪⼼策略:
    分情况讨论:
    a. 遇到 5 元钱,直接收下;
    b. 遇到 10 元钱,找零 5 元钱之后,收下;
    c. 遇到 20 元钱:
    i. 先尝试凑 10 + 5 的组合;
    ii. 如果凑不出来,拼凑 5 + 5 + 5 的组合;
  4. C++代码
class Solution {
public:
    bool lemonadeChange(vector<int>& bills) 
    {
        int five=0,ten=0;
        for(int i=0;i<bills.size();i++)
        {
            if(bills[i]==5)
                five++;
            else if(bills[i]==10)
            {
                ten++;
                if(five>0)five--;
                else return false;
            }
            else
            {
                if(ten>0&&five>0)//贪心
                {
                    ten--;
                    five--;
                }
                else if(five>=3)five-=3;
                else return false;
            }
        }
        return true;
    }
};

1.2 将数组和减半的最少操作次数

  1. 题⽬链接:2208. 将数组和减半的最少操作次数
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(贪⼼):
    贪⼼策略:
    a. 每次挑选出「当前」数组中「最⼤」的数,然后「减半」
    b. 直到数组和减少到⾄少⼀半为⽌。
    为了「快速」挑选出数组中最⼤的数,我们可以利⽤「堆」这个数据结构
  4. C++代码
class Solution {
    double sum=0,cnt=0;
    priority_queue<double,vector<double>,less<double>> pq;
public:
    int halveArray(vector<int>& nums) 
    {
        for(auto&e:nums)
        {  
            sum+=e;
            pq.push(e);
        }
        sum/=2.0;
        while(sum>0)
        {
            cnt++;
            double tmp=pq.top()/2;
            pq.pop();
            sum-=tmp;
            pq.push(tmp);
        }
        return cnt;
    }
};

1.3 最⼤数

  1. 题⽬链接:179. 最⼤数
  2. 题⽬描述
    在这里插入图片描述
  3. 解法(贪⼼):
    可以先优化:将所有的数字当成字符串处理,那么两个数字之间的拼接操作以及⽐较操作就会很⽅便。
    贪⼼策略:按照题⽬的要求,重新定义⼀个新的排序规则,然后排序即可。
    排序规则:
    a. 「A 拼接 B」 ⼤于 「B 拼接 A」,那么 A 在前,B 在后;
    b. 「A 拼接 B」 等于 「B 拼接 A」,那么 A B 的顺序⽆所谓;
    c. 「A 拼接 B」 ⼩于 「B 拼接 A」,那么 B 在前,A 在后;
  4. C++代码
class Solution {
public:
    string largestNumber(vector<int>& nums) 
    {
        vector<string> v;
        for(auto&e:nums)
        v.push_back(to_string(e));
        string ret;
        sort(v.begin(),v.end(),[](string& s1,string& s2){
            return s1+s2>s2+s1;
        });
        for(int i=0;i<v.size();i++)
        {
            if(i==0&&v[i]=="0")return "0";
            ret+=v[i];
        }
        return ret;
    }
};

1.4 摆动序列

  1. 题⽬链接:376. 摆动序列
  2. 题⽬描述
    在这里插入图片描述
  3. 解法(贪⼼):
    贪⼼策略:
    对于某⼀个位置来说:
    ◦ 如果接下来呈现上升趋势的话,我们让其上升到波峰的位置;
    ◦ 如果接下来呈现下降趋势的话,我们让其下降到波⾕的位置。
    因此,如果把整个数组放在「折线图」中,我们统计出所有的波峰以及波⾕的个数即可。
  4. C++代码
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) 
    {
        int left=0,ret=0;
        for(int i=0;i<nums.size()-1;i++)
        {
            int right=nums[i+1]-nums[i];
            if(right==0)continue;
            if(right*left<=0)ret++;
            left=right;
        }
        return ret+1;//加上最后一个
    }
};

1.5 最⻓递增⼦序列

  1. 题⽬链接:300. 最⻓递增⼦序列
  2. 题⽬描述:
    在这里插入图片描述
  3. 解法(贪⼼):
    贪⼼策略:
    我们在考虑最⻓递增⼦序列的⻓度的时候,其实并不关⼼这个序列⻓什么样⼦,我们只是关⼼最后⼀个元素是谁这样新来⼀个元素之后,我们就可以判断是否可以拼接到它的后⾯
    因此,我们可以创建⼀个数组,统计⻓度为 x 的递增⼦序列中,最后⼀个元素是谁。为了尽可能的让这个序列更⻓,我们仅需统计⻓度为 x 的所有递增序列中最后⼀个元素的「最⼩值」。
    统计的过程中发现,数组中的数呈现「递增」趋势,因此可以使⽤「⼆分」来查找插⼊位置
  4. C++代码
class Solution {
    int cnt=0;
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]);//可以拼接到后面
     //如果不可以拼接到末尾则需要找到ret中出现第一次>=nums[i]的值进行替换,也就是把这个第一次大的值换成小的nums[i]
            else
            {
                int left=0,right=ret.size()-1;
                while(left<right)
                {
                    int mid=left+(right-left)/2;
                    if(ret[mid]>=nums[i])right=mid;
                    else left=mid+1;
                }
                ret[left]=nums[i];
            }
        }
        return ret.size();
    }
};

1.6 递增的三元⼦序列

  1. 题⽬链接:334. 递增的三元⼦序列
  2. 题⽬描述
    在这里插入图片描述
  3. 解法(贪⼼):
    贪⼼策略:
    最⻓递增⼦序列的简化版。
    不⽤⼀个数组存数据,仅需两个变量即可。也不⽤⼆分插⼊位置,仅需两次⽐较就可以找到插⼊位置
  4. C++代码
class Solution {
public:
    bool increasingTriplet(vector<int>& nums) 
    {
        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-left)/2;
                    if(nums[i]>ret[mid])left=mid+1;
                    else right=mid;
                }
                ret[left]=nums[i];
            }
        }
        return ret.size()>=3?true:false;
    }
};
----------------------------------------------------------------------------------------------
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)a=nums[i];
                else b=nums[i];
            }
        }
        return false;
    }
};

http://www.niftyadmin.cn/n/5743228.html

相关文章

那些在Nop代码生成器中用到的DSL

Nop平台基于所谓的可逆计算理论从零开始编写&#xff0c;它的整体实现可以看作是如下软件构造公式在不同抽象层面的反复应用 App Delta x-extends Generator<DSL> 为了将这个抽象公式落实为具体的技术实现&#xff0c;Nop平台内置了一系列的通用机制&#xff0c;用于实现…

《深度学习》——深度学习基础知识(全连接神经网络)

文章目录 1.神经网络简介2.什么是神经网络3.神经元是如何工作的3.1激活函数3.2参数的初始化3.2.1随机初始化3.2.2标准初始化3.2.3Xavier初始化&#xff08;tf.keras中默认使用的&#xff09;3.2.4He初始化 4.神经网络的搭建4.1通过Sequential构建神经网络4.2通过Functional API…

IPD开发流程与传统开发流程的区别

大部分科技型企业都建立了自己的新产品开发流程&#xff0c;而且很多都是基于ISO9000或TS16949等标准设计的&#xff0c;不少软件类企业倾向于按照CMMI或敏捷开发&#xff08;敏捷开发不在本文探讨范围&#xff09;建立开发流程&#xff0c;但绝大多数开发流程发挥的作用不理想…

立体视觉的核心技术:视差计算与图像校正详解

立体视觉的核心技术&#xff1a;视差计算与图像校正详解 在立体视觉中&#xff0c;通过双目相机&#xff08;即左右两台相机&#xff09;的不同视角捕获的图像&#xff0c;结合几何关系&#xff0c;我们可以推算出场景中物体的深度。本文将深入讲解如何基于视差&#xff08;di…

3DMax使用 MCG实现简单克隆修改器

3DMax中的MCG工具集允许用户创建几种不同类型的插件。在这个例子中&#xff0c;我们正在创建一个简单的克隆修改器。 将修改器添加到对象时&#xff0c;将使用“数量”整数值克隆网格n次&#xff0c;并使用X、Y和Z中的“缩放”、“旋转”和“移动”微调器控制每个网格的偏移。…

【解决】Pico 串流 Unity 开发环境 Preview 黑屏问题

开发平台&#xff1a;Unity 6.0 开发工具&#xff1a;Pico SDK   一、问题描述 在 Unity 开发环境下运行 测试 PicoVR 表现时&#xff0c;出现 Game视窗 PicoVR投屏 呈现黑屏效果。详细背景如下&#xff1a; UnitySwitch PlateformPICO Integration SDKPICO Live Preview6…

解决OBS屏幕录制输出mp4视频文件太大问题

一、背景 刚使用OBS录屏&#xff0c;不清楚其设置&#xff0c;默认情况下其使用的“编码器”是“硬件QSV”&#xff0c;导致我录3分钟的屏&#xff0c;输出的视频文件竟然将近60M&#xff0c;逆天&#xff1b; 且无论我如何调整码率、输出格式、输出质量级别这些参数都没有显著…

javadoc:JDK 9 下使用自定义Doclet调用JavadocTool的两种方案

前阵子写过一篇博客文章&#xff1a;《javadoc:jdk 9通过javadoc API读取java源码中的注释信息(comment)》介绍了在JDK9下通过JavadocTool 执行javadoc&#xff0c;使用自定义Doclet读取源码注释的基本过程。 我当时的工作是为了将这个过程封装为一个独立项目javadocreader9&a…