贪心算法专题(一)

news2024/9/27 7:25:24

目录

1、贪心算法简介

1.1 什么是贪心算法

1.2 贪心算法的特点

1.3 贪心算法的学习方向

2、算法应用【leetcode】

2.1 题一:柠檬水找零

2.1.1 算法原理

2.1.2 算法代码

2.2 题二:将数组和减半的最少操作次数

 2.2.1 算法原理

2.2.2 算法代码

2.3 题三:最大数

2.3.1 算法原理

2.3.2 算法代码

2.4 题四:摆动序列

2.4.1 算法原理

2.4.2 算法代码

2.5 题五:最长递增子序列

2.5.1 算法原理1——记忆化搜索

2.5.2 算法代码1——记忆化搜索

2.5.3 算法原理2——动态规划

2.5.4 算法代码2——动态规划

2.5.5 算法原理3——贪心+二分【最优解】

2.5.6 算法代码3——贪心+二分【最优解】


1、贪心算法简介

1.1 什么是贪心算法

贪心算法(greedy algorithm ,又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择在每一步选择中都采取当前状态下最优的选择,以期望达到全局最优解的算法策略‌。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解

贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择。

贪心算法的核心就是:贪心策略。

而贪心策略就是由:局部最优解 推算出 全局最优解。

  1. 将解决问题的分为若干步,逐步击破
  2. 解决每一步时,选择当前步“最优的”解法
  3. “希望”得到全局最优解

1.2 贪心算法的特点

我们可能是猜的、蒙的、靠直觉想出的贪心策略,所以贪心策略的正确性的不确定的。

贪心策略的提出:

  1. 贪心算法和我们之前所学到的算法不同,贪心策略的提出是没有任何固定的模版或者标准的
  2. 每一道题的贪心策略都是不同的

贪心策略的正确性:

  1. 贪心策略可能是错误的
  2. 贪心策略需要各种数学方法的证明

1.3 贪心算法的学习方向

由于每一道题的贪心策略都可能不同,所以即使我们做了几十道贪心题后,再面对对于一道新贪心题时,也可能会没有任何的思路。所以遇到不会的贪心题是很正常的,我们要把心态放平。

  1. 在前期学习时,将每道题的贪心策略当做经验来吸收,扩大对贪心策略的认知。
  2. 不用纠结别人的贪心策略是怎么想出的,想不出来很正常,我们当做经验把策略吸收即可。

2、算法应用【leetcode】

2.1 题一:柠檬水找零

. - 力扣(LeetCode)

2.1.1 算法原理

 对于5元和10元的找零策略是固定的,给20元找零时有两种策略:要么找三张5元;要么找一张5元和一张10元。

经过分析:5元的用处更多(给10元找零时要用),所以要尽可能的保留5元。

故,贪心策略为:给20元找一张5元和一张10元;当10元不存在时才找三张5元。

2.1.2 算法代码

class Solution {
    public boolean lemonadeChange(int[] bills) {
        //<金额, 个数>
        int five = 0, ten = 0;
        if(bills[0] != 5) return false;
        for(int i = 0; i < bills.length; i++) {
            if(bills[i] == 5) five++;
            else if(bills[i] == 10) {
                if(five == 0) return false;
                five--; ten++;
            }else {
                if(five == 0) {
                    return false;
                }else if(ten != 0) {
                    //贪心
                    ten--;
                    five--;
                }else {
                    if(five < 3) return false;
                    five -= 3;
                }
            }
        }
        return true;
    }
}

2.2 题二:将数组和减半的最少操作次数

. - 力扣(LeetCode)

 2.2.1 算法原理

策略:贪心+大根堆

  1. 因为求使数组减半的最小的操作次数,
  2. 根据贪心策略,每次将数组中最大的元素进行减半操作,这样可使得操作次数最少。
  3. 循环这个过程,直至将数组和减半。

2.2.2 算法代码

class Solution {
    public int halveArray(int[] nums) {
        double sum = 0;
        //建大堆
        PriorityQueue<Double> queue = new PriorityQueue<>((o1,o2) -> o2.compareTo(o1));
        for (int i = 0; i < nums.length; i++) {
            sum += nums[i];
            queue.offer((double)nums[i]);
        }
        sum /= 2;
        int count = 0;
        while (sum > 0) {
            double peek = queue.poll();
            sum -= peek / 2;
            queue.offer(peek / 2);
            count++;
        }
        return count;
    }
}

2.3 题三:最大数

. - 力扣(LeetCode)

2.3.1 算法原理

本质:确定数组中元素的先后顺序(谁在前,谁在后)

核心:修改sort方法的排序规则 -> 进行元素拼接后的比较,将拼接后的较大的元素放在前面。

优化:使用字符串进行拼接

2.3.2 算法代码

class Solution {
    public String largestNumber(int[] nums) {
        String[] strs = new String[nums.length];
        for (int i = 0; i < nums.length; i++)
            strs[i] = nums[i] + "";
        Arrays.sort(strs, (o1, o2) -> (o2 + o1).compareTo(o1 + o2));
        StringBuffer sb = new StringBuffer();
        for (String str : strs)
            sb.append(str);
        if (sb.charAt(0) == '0')
            return "0";
        return sb.toString();
    }
}

2.4 题四:摆动序列

. - 力扣(LeetCode)

2.4.1 算法原理

画出数组元素值的折线图,可以发现每次选取极值点可以使摆动序列的长度最大。

  • 贪心策略:选取折线图的极值点,计算极值点的个数。
  • 为什么该策略为贪心策略呢?——因为选取极大值或极小值,在下次选取元素时(满足摆动序列)会有更多的选择性(贪心策略),不会漏掉数据。

2.4.2 算法代码

class Solution {
    int left;//左侧的增减性
    int ret;
    public int wiggleMaxLength(int[] nums) {
        for(int i = 0; i < nums.length - 1; i++) {
            //右侧的增减性
            int right = nums[i + 1] - nums[i];
            //右侧元素与当前元素相同
            if(right == 0) continue;
            //极值点
            if(right * left <= 0) ret++;   
            left = right;
        }
        //加上最后一个节点
        return ret + 1;
    }
}

2.5 题五:最长递增子序列

. - 力扣(LeetCode)

2.5.1 算法原理1——记忆化搜索

算法核心:

  • dfs当前元素(pos位置)后面位置的元素(要求:nums[pos] < nums[后面序列]),寻找出最长递增子序列的长度,再加一(算上当前节点),就是以当前位置为起点的最长递增子序列的长度。

备忘录优化(记忆化搜索):

  • 使用memo数组存储以该位置为起点的最长递增子序列的长度。

2.5.2 算法代码1——记忆化搜索

class Solution {
    //记忆化搜索
    int ret = 1;
    int path;
    int[] memo;
    public int lengthOfLIS(int[] nums) {
        memo = new int[nums.length];
        int ret = 0;
        for(int i = 0; i < nums.length; i++) {
            ret = Math.max(ret, dfs(nums, i));
        }
        return ret;
    }
    public int dfs(int[] nums, int pos) {
        int ret = 1;
        if(memo[pos] != 0) return memo[pos];
        for(int i = pos + 1; i < nums.length; i++) {
            if(nums[i] > nums[pos]) {
                ret = Math.max(ret, dfs(nums, i) + 1);
            }
        }
        memo[pos] = ret;
        return ret;
    }
}

2.5.3 算法原理2——动态规划

算法核心:

  • 状态表示(dp[i]):以当前位置为结尾的最长递增子序列的长度
  • 状态转移方程:dp[i]=max(dp[j] + 1)【要求:(j < i && nums[j] < nums[i])】

2.5.4 算法代码2——动态规划

class Solution {
    //动态规划
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        int[] dp = new int[n];
        Arrays.fill(dp, 1);
        for(int i = 0; i < n; i++) {
            for(int j = i - 1; j >= 0; j--) {
                if(nums[j] < nums[i]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                }
            }
        }
        int max = 0;
        for(int x : dp) max = Math.max(max, x);
        return max;
    }
}

2.5.5 算法原理3——贪心+二分【最优解】

本题最优解为贪心算法。时间复杂度为O(N*logN)

贪心策略的核心,在于以下两点:

  1. 存什么:每个长度的递增序列中,存的是最后一个元素的最小值(假设x后面可以有一段递增序列,那么比x更小的数后面也一定可以有这个序列)【将数据存入数组hash中】
  2. 存哪里:存第一个大于等于nums[i]的位置(覆盖删除)

光靠文字也许晦涩难懂,下文已放图。 

如果我们仅仅按照以上策略来贪心的话,每个新元素查找插入位置的时间为O(N),整体的时间复杂度也依然是O(N^2),但是发现我们存放数据的数组hash满足递增的特性,故我们可以使用二分的方法寻找插入位置——优化为O(logN),将整体的时间复杂度优化为:O(N*logN)

所以本题的解题原理为:贪心策略 + 二分查找 

2.5.6 算法代码3——贪心+二分【最优解】

class Solution {
    //贪心 + 二分查找
    public int lengthOfLIS(int[] nums) {
        int n = nums.length;
        List<Integer> hash = new ArrayList<>();
        for(int i = 0; i < n; i++) {
            int val = nums[i];
            int left = 0, right = hash.size() - 1;
            //hash为空
            //新元素比所有元素都大时,直接插入到最后
            if(hash.size() == 0 || val > hash.get(right)) {
                hash.add(val);
                continue;
            }
            //二分插入位置(hash为有序数组)
            while(left < right) {
                int mid = left + (right - left) / 2;
                if(hash.get(mid) < val) left = mid + 1;
                else right = mid; 
            }
            hash.set(left, val);
        }
        return hash.size();
    }
}

END

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenCV图像文件读写(4)解码图像数据函数imdecode()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 从内存缓冲区读取图像。 imdecode 函数从指定的内存缓冲区读取图像。如果缓冲区太短或包含无效数据&#xff0c;函数将返回一个空矩阵 (Mat::dat…

双十一数码什么值得买?盘点双十一最值得入手的数码好物

每年双11已经成为了人们购物的重要节点&#xff0c;除了手机外的其他数码产品也是购物清单上不可或缺的一部分。我们的生活和工作中&#xff0c;使用的数码产品越来越多。是时候给大家种草一波3C数码好物了&#xff0c;键盘、鼠标、平板、耳机、显示器啥都有&#xff0c;产品虽…

Web端云剪辑解决方案,支持多种滤镜、转场、贴纸、粒子、蒙版类特效效果

美摄科技隆重推出其革命性的Web端云剪辑解决方案&#xff0c;旨在为全球创作者提供一站式、高效能、云端化的视频编辑新体验&#xff0c;让视频创作不再受限于时间与空间&#xff0c;轻松实现专业级的视觉效果。 【云端赋能&#xff0c;创意无界】 美摄科技的Web端云剪辑解决…

“接口测试简介”——实现接口测试,软件自动化测试入门攻略

实现接口测试 接口测试是检查程序各部分之间的交互点&#xff0c;从无测试到手工测试、借助脚本或工具实现自动化测试以及测试平台的构建&#xff0c;接口测试近几年发展非常迅速&#xff0c;许多企业也都开始重视接口测试&#xff0c;因此&#xff0c;接口测试也成了测试人员…

php在线相册

1、将静态页面效果完成 解压到www里 整个数据 暂时是错误的 建立连接密码为root 运行sql文件 开始 测试 导入alumbenew2 2.提交表单方式 3.利用php获取表单值的方法

三目运算判断字母大小写-C语言

1.问题&#xff1a; 输入一个字符&#xff0c;判别它是否为大写字母&#xff0c;如果是&#xff0c;将它转换成小写&#xff0c;如果不是&#xff0c;不转换。然后输出最后得到的字符&#xff0c;要求使用三目运算符。 2.解答&#xff1a; 用条件表达式来处理&#xff0c;当字…

【C++进阶】2024年了set、map还搞不懂底层细节?

&#x1f680;个人主页&#xff1a;小羊 &#x1f680;所属专栏&#xff1a;C 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 一、前情提要1、什么是关联式容器&#xff1f;2、键值对又是什么&#xff1f; 二、树形结构的关联式容器1、set1.1…

细说机房安装带孔的通风防静电地板的原因

静电在我们的日常生活中无处不在&#xff0c;但在机房等特殊环境中&#xff0c;静电却可能带来巨大的危害&#xff0c;为了防止静电带来的危害&#xff0c;很多机房都会安装防静电地板。其中有一部分机房会安装带孔的通风防静电地板&#xff0c;那么带孔的通风防静电地板有什么…

小程序-生命周期与WXS脚本

生命周期 什么是生命周期 生命周期&#xff08;Life Cycle&#xff09;是指一个对象从创建 -> 运行 -> 销毁的整个阶段&#xff0c;强调的是一个时间段。 我们可以把每个小程序运行的过程&#xff0c;也概括为生命周期&#xff1a; 小程序的启动&#xff0c;表示生命…

Java免税商品购物商城:Spring Boot实现详解

第一章 绪论 1.1 课题开发的背景 从古至今&#xff0c;通过书本获取知识信息的方式完全被互联网络信息化&#xff0c;但是免税商品优选购物商城&#xff0c;对于购物商城工作来说&#xff0c;仍然是一项非常重要的工作。尤其是免税商品优选购物商城&#xff0c;传统人工记录模式…

夹耳蓝牙耳机哪个品牌质量最好最耐用?2024年耳夹式耳机选购指南

随着科技的进步和人们对音质要求的提高&#xff0c;耳夹式耳机逐渐成为大家的耳机新宠。但是&#xff0c;面对市场上琳琅满目的耳夹式耳机品牌&#xff0c;许多人都会困惑&#xff1a;夹耳蓝牙耳机哪个品牌质量最好最耐用&#xff1f;其实&#xff0c;选对品牌不仅关系到音质的…

计算机前沿技术-人工智能算法-生成对抗网络-算法原理及应用实践

计算机前沿技术-人工智能算法-生成对抗网络-算法原理及应用实践 1. 什么是生成对抗网络&#xff1f; 生成对抗网络&#xff08;Generative Adversarial Networks&#xff0c;简称GANs&#xff09;是由Ian Goodfellow等人在2014年提出的一种深度学习模型&#xff0c;主要用于数…

OpenHarmony(鸿蒙南向)——平台驱动开发【PIN】

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 概述 功能简介 PIN即管脚控制器&#xff0c;用于统一管理各SoC的…

Python 在PDF中插入文本超链接和图片超链接 (详解)

目录 使用工具 Python给PDF添加网页链接 Python给PDF添加内部文件链接 Python给PDF添加外部文件链接 Python给PDF中现有文本添加超链接 Python在PDF中插入带超链接的图片 Python给PDF中现有图片添加超链接 超链接是指向特定资源&#xff08;如外部网页、文档内部位置或其…

Android个性名片界面的设计——约束布局的应用

节选自《Android应用开发项目式教程》&#xff0c;机械工业出版社&#xff0c;2024年7月出版 做最简单的安卓入门教程&#xff0c;手把手视频、代码、答疑全配齐 【任务目标】 使用约束布局、TextView控件实现一个个性名片界面的设计&#xff0c;界面如图1所示。 图1 个性名片…

跟王道学c记录

scanf int a; scanf("%d",&a); 一定要有取地址符 printf 用%f精度修饰符指定想要的小数位数。例如,%5.2f会至少显示5位数字并带有2位小 数的浮点数 用%s精度修饰符简单地表示一个最大的长度,以补充句点前的最小字段长度 printf 数的所有输出都是右对齐的,除非…

C++的哲学思想

C的哲学思想 文章目录 C的哲学思想&#x1f4a1;前言&#x1f4a1;C的哲学思想☁️C底层不应该基于任何其他语言&#xff08;汇编语言除外&#xff09;☁️只为使用的东西付费&#xff08;不需要为没有使用到的语言特性付费&#xff09;☁️以低成本提供高级抽象&#xff08;更…

exBase

1.准备工作 1.端口配置 下列为默认端口号&#xff0c;若部分端口号已被占用&#xff0c;用户可以根据实际情况进行修改。 端口号 说明 31030 exBase默认端口 31003 配置库默认端口 2181 zookeeper默认端口 9092 kafka默认端口 8091 metaNode的RPC端口 8092 node…

【Linux】进程管理:从理论到实践(一)

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a; &#x1f525; 进程的基本概念 二&#xff1a; &#x1f525; 描述进程-PCB三&#xff1a; &#x1f525; 查看进程 &#x1f95d; 通过系统目录&#x1f95d; 通过ps命…

小程序视频编辑SDK解决方案,轻量化视频制作解决方案

面对小程序、网页、HTML5等多样化平台&#xff0c;如何轻松实现视频编辑的轻量化与高效化&#xff0c;成为了众多开发者和内容创作者共同面临的挑战。正是洞察到这一市场需求&#xff0c;美摄科技推出了其领先的小程序视频编辑SDK解决方案&#xff0c;为创意插上翅膀&#xff0…