您当前的位置:首页 > 电脑百科 > 程序开发 > 算法

python算法基础之贪心算法

时间:2022-04-22 12:00:06  来源:  作者:北漂的乔峰

贪心算法概述

贪心算法(又称贪婪算法),基本原理是,遵循某种既定原则,不断地选取当前条件下最优的选择来构造每一个子步骤,直到获得问题最终的求解。即在求解时,总是作出当前看来最好的选择。也就是说,不从整体最优上加以考虑,仅是求解局部最优解,以期望能找到全局最优解。

贪心算法与动态规划类似,都是将原来的较大规模的问题拆分为规模较小的问题,依据大问题与小问题之间的递推关系,通过解决较小规模的问题,最终获得原始问题的求解。但是动态规划要通盘考虑各个阶段各子问题的求解情况,从全局的角度进行衡量,最终找到解决原始问题的最佳解决方案。贪心算法与动态规划的不同之处在于,贪心算法利用问题的贪心性质,简化了分解原始问题的过程,每次只关注在当前状态下可以获得的局部最优解,通过拼接各阶段的局部最优解获得最终问题的解。因为贪心选择可以依赖于以往所做的选择,但绝不依赖于未来所做的选择,也不依赖于子问题的解。故而贪心算法往往求解时与动态规划相反,采用自顶向下的方式,迭代作出贪心选择,不断化简问题规模

利用贪心算法解题,需要解决两个问题:

  • 是否适合用贪心法求解,即所求解问题是否具有贪心选择性质。所谓贪心选择性质是指应用同一规则,将原问题变为一个相似的但规模更小的子问题,而后的每一步都是当前看似最佳的选择。这种选择依赖于已做出的选择,但不依赖于未做出的选择。从全局来看,运用贪心策略解决的问题在程序的运行过程中无回溯过程。贪心选择性质的证明一般采用数学归纳法,证明每一步做出的贪心选择确实能导致问题的整体(全局)最优解,也有基于算法的输出,或使用一种“拟阵”结构等形式的证明。
  • 是否具有局部最优解,从而通过选择一个贪心标准,可以得到问题的最优解。贪心算法和动态规划都依赖于问题具有最优子结构性质,但并不是具有最优子结构性质的问题就可以用贪心算法求解。贪心算法不是总能对动态规划求解最优化问题进行优化的。

贪心算法解题思路

  1. 建立对问题精确描述的数学模型,包括定义最优解的模型;
  2. 将问题分成一系列的子问题,同时定义子问题的最优解结构;
  3. 应用贪心算法原则可以确定每个子问题的局部最优解,并根据最优解模型,用子问题的局部最优解堆叠出全局最优解。

代码示例

  • 硬币找零问题是给定找零金额,计算如何搭配使得使用的硬币数量最少
# 硬币找零问题是给定找零金额,计算如何搭配使得使用的硬币数量最少
def get_change(coins, amount):
    coins.sort()
    # 从面值最大的硬币开始遍历
    i = len(coins) - 1
    di = {}
    while i >= 0:
        if amount >= coins[i]:
            n = int(amount // coins[i])
            change = n * coins[i]
            amount -= change
            di[coins[i]] = n
        i -= 1
    return di
  • 哈夫曼编码

现在有一个包含 5 个字符的字符表 {A,B,C,D,E},各字符出现的频率A:0.35, B:0.1, C:0.2, D:0.2, E:0.15;

构造一种有效率的编码类型,使用该编码表达以上字符表内容时可以产生平均长度最短的位串。在对由 n 个字符组成的文本进行编码过程中,有两种编码方式,即定长编码和变长编码。对于定长编码而言,会为每个字符赋予一个长度固定为 m(m≥log2n) 的位串,我们常用的标准 ASCII 码就是采用定长编码策略对字符集进行编码的。长度各异的编码,其中出现频率较高的字符,采用长度较短的编码表示,出现频率较低的字符,采用长度较长的编码表示。

为了对某字母表构造一套二进制的前缀码,可以借助二叉树。将树中所有的左向边都标记为0,所有的右向边都标记为 1。通过记录从根节点到字符所在的叶子节点的简单路径上的所有 0-1 标记来获得表示该字符的编码。

# 参考文档: https://www.92Python/ target=_blank class=infotextkey>Python.com/view/354.html
# 树节点定义
class Node:
    def __init__(self, pro):
        self.left = None
        self.right = None
        self.parent = None
        self.pro = pro

    def is_left(self):  # 判断左子树
        return self.parent.left == self

# create nodes创建叶子节点
def create_nodes(pros):
    return [Node(pro) for pro in pros]

# create Huffman-Tree创建Huffman树
def create_huffman_tree(nodes):
    """从下向上创建二叉树"""
    queue = nodes[:]
    while len(queue) > 1:
        queue.sort(key=lambda item: item.pro)
        node_left = queue.pop(0)
        node_right = queue.pop(0)
        node_parent = Node(node_left.pro + node_right.pro)  # 二节点值合并
        node_parent.left = node_left  # 父亲认儿子,
        node_parent.right = node_right
        node_left.parent = node_parent  # 儿子认父亲
        node_right.parent = node_parent
        queue.Append(node_parent)
    queue[0].parent = None
    return queue[0]

# Huffman编码
def huffman_encoding(nodes, root):
    """根据当前节点为左右子树进行判断赋值"""
    codes = [''] * len(nodes)
    for i in range(len(nodes)):
        node_temp = nodes[i]
        while node_temp != root:
            if node_temp.is_left():
                codes[i] = '0' + codes[i]
            else:
                codes[i] = '1' + codes[i]
            node_temp = node_temp.parent  # 当前节点替换为父子节点
    return codes

if __name__ == '__mAIn__':
    letters_pros = [('B', 10), ('E', 15), ('C', 20), ('D', 20), ('A', 35)]
    nodes = create_nodes([item[1] for item in letters_pros])  # 生成树节点
    root = create_huffman_tree(nodes)
    codes = huffman_encoding(nodes, root)
    for item in zip(letters_pros, codes):
        print('Label:%s pro:%-2d Huffman Code:%s' % (item[0][0], item[0][1], item[1]))

哈夫曼树:

python算法基础之贪心算法

 

总结

  • 贪心算法需要具备贪心选择性质和最优子结构性质
  • 动态规划和贪心算法的计算顺序是相反的,动态规划由下而上,贪心从顶而下;


Tags:贪心算法   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
python算法基础之贪心算法
贪心算法概述贪心算法(又称贪婪算法),基本原理是,遵循某种既定原则,不断地选取当前条件下最优的选择来构造每一个子步骤,直到获得问题最终的求解。即在求解时,总是作出当前看来最好...【详细内容】
2022-04-22  Search: 贪心算法  点击:(438)  评论:(0)  加入收藏
贪心算法经典题目:分发糖果
我将算法学习相关的资料已经整理到了Github :https://github.com/youngyangyang04/leetcode-master,里面还有leetcode刷题攻略、各个类型经典题目刷题顺序、思维导图看一看一...【详细内容】
2020-12-15  Search: 贪心算法  点击:(993)  评论:(0)  加入收藏
贪心算法:分发饼干
分发饼干题目链接:https://leetcode-cn.com/problems/assign-cookies/假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i,都...【详细内容】
2020-11-25  Search: 贪心算法  点击:(723)  评论:(0)  加入收藏
贪心算法简介
贪婪算法贪心算法(Greedy Algorithm) 简介贪心算法,又名贪婪法,是寻找最优解问题的常用方法,这种方法模式一般将求解过程分成若干个步骤,但每个步骤都应用贪心原则,选取当前状态下...【详细内容】
2020-01-14  Search: 贪心算法  点击:(533)  评论:(0)  加入收藏
C++编程笔记:贪心算法实现部分背包问题
问题描述:在部分背包问题中,可以不必拿走整个一件物品,而是可以拿走该物品的任意部分。以此求得在限定背包总重量,从给定的物品中进行选择的情况下的最佳(总价值最高)的选择方案...【详细内容】
2019-11-07  Search: 贪心算法  点击:(788)  评论:(0)  加入收藏
贪心算法
定义贪心算法是指每一步都求最优解,迭代求得可能是全局最优解的算法。当然局部最优解可能不是全局最优解,也可能是全局最优解,这就要看选择的贪心策略了。一般证明选择的策略是...【详细内容】
2019-08-27  Search: 贪心算法  点击:(962)  评论:(0)  加入收藏
▌简易百科推荐
小红书、视频号、抖音流量算法解析,干货满满,值得一看!
咱们中国现在可不是一般的牛!网上的网友已经破了十个亿啦!到了这个互联网的新时代,谁有更多的人流量,谁就能赢得更多的掌声哦~抖音、小红书、、视频号,是很多品牌必争的流量洼地...【详细内容】
2024-02-23  二手车小胖说    Tags:流量算法   点击:(17)  评论:(0)  加入收藏
雪花算法详解与Java实现:分布式唯一ID生成原理
SnowFlake 算法,是 Twitter 开源的分布式 ID 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛,且 ID 引入了时间戳...【详细内容】
2024-02-03   一安未来  微信公众号  Tags:雪花算法   点击:(54)  评论:(0)  加入收藏
程序开发中常用的十种算法,你用过几种?
当编写程序时,了解和使用不同的算法对解决问题至关重要。以下是C#中常用的10种算法,每个算法都伴随着示例代码和详细说明。1. 冒泡排序 (Bubble Sort):冒泡排序是一种简单的比...【详细内容】
2024-01-17  架构师老卢  今日头条  Tags:算法   点击:(46)  评论:(0)  加入收藏
百度推荐排序技术的思考与实践
本文将分享百度在推荐排序方面的思考与实践。在整个工业界的推广搜场景上,特征设计通常都是采用离散化的设计,需要保证两方面的效果,一方面是记忆,另一方面是泛化。特征都是通过...【详细内容】
2024-01-09  DataFunTalk  微信公众号  Tags:百度推荐   点击:(80)  评论:(0)  加入收藏
什么是布隆过滤器?如何实现布隆过滤器?
以下我们介绍了什么是布隆过滤器?它的使用场景和执行流程,以及在 Redis 中它的使用,那么问题来了,在日常开发中,也就是在 Java 开发中,我们又将如何操作布隆过滤器呢?布隆过滤器(Blo...【详细内容】
2024-01-05  Java中文社群  微信公众号  Tags:布隆过滤器   点击:(91)  评论:(0)  加入收藏
面向推荐系统的深度强化学习算法研究与应用
随着互联网的快速发展,推荐系统在各个领域中扮演着重要的角色。传统的推荐算法在面对大规模、复杂的数据时存在一定的局限性。为了解决这一问题,深度强化学习算法应运而生。本...【详细内容】
2024-01-04  数码小风向    Tags:算法   点击:(104)  评论:(0)  加入收藏
非负矩阵分解算法:从非负数据中提取主题、特征等信息
非负矩阵分解算法(Non-negativeMatrixFactorization,简称NMF)是一种常用的数据分析和特征提取方法,主要用于从非负数据中提取主题、特征等有意义的信息。本文将介绍非负矩阵分解...【详细内容】
2024-01-02  毛晓峰    Tags:算法   点击:(73)  评论:(0)  加入收藏
再谈前端算法,你这回明白了吗?
楔子 -- 青蛙跳台阶一只青蛙一次可以跳上一级台阶,也可以跳上二级台阶,求该青蛙跳上一个n级的台阶总共需要多少种跳法。分析: 当n=1的时候,①只需要跳一次即可;只有一种跳法,即f(...【详细内容】
2023-12-28  前端爱好者  微信公众号  Tags:前端算法   点击:(113)  评论:(0)  加入收藏
三分钟学习二分查找
二分查找是一种在有序数组中查找元素的算法,通过不断将搜索区域分成两半来实现。你可能在日常生活中已经不知不觉地使用了大脑里的二分查找。最常见的例子是在字典中查找一个...【详细内容】
2023-12-22  小技术君  微信公众号  Tags:二分查找   点击:(79)  评论:(0)  加入收藏
强化学习算法在资源调度与优化中的应用
随着云计算和大数据技术的快速发展,资源调度与优化成为了现代计算系统中的重要问题。传统的资源调度算法往往基于静态规则或启发式方法,无法适应动态变化的环境和复杂的任务需...【详细内容】
2023-12-14  职场小达人欢晓    Tags:算法   点击:(169)  评论:(0)  加入收藏
站内最新
站内热门
站内头条