Python实战开发及案例分析(5)—— 贪心算法

        贪心算法是一种在每一步选择中都采取当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法。贪心算法不能保证得到最优解,但在某些问题中非常有效,并容易实现。

案例分析:找零问题

项目背景:假设你是一名收银员,需要给顾客找零,你的目标是在给出确切金额的同时,使用尽可能少的硬币。

问题设定
  • 有不同面额的硬币:1分,5分,10分,25分。
  • 需要找给顾客确切的零钱,同时使用最少的硬币。
使用 Python 实现贪心算法
def greedy_coin_change(amount, coins):# 初始化result = []# 从最大的硬币开始尝试for coin in sorted(coins, reverse=True):while amount >= coin:amount -= coinresult.append(coin)return result# 硬币面额
coins = [1, 5, 10, 25]# 找零金额
amount = 63# 调用函数
change = greedy_coin_change(amount, coins)# 输出结果
print("Coins to give:", change)
print("Number of coins:", len(change))
结果分析

        这个贪心算法从最大的硬币开始,尽可能多地使用每种硬币,直到找零金额被减至零。在这种情况下,算法能够有效地减少需要使用的硬币数量。

更复杂的案例:活动选择问题

项目背景:你有一系列活动,每个活动都有一个开始时间和结束时间。你的目标是安排尽可能多的活动,使得活动之间不相互冲突。

问题设定
  • 活动由其开始和结束时间定义。
  • 选择的活动集合中任何两个活动都不能有时间上的重叠。
使用 Python 实现贪心算法
def activity_selection(activities):# 根据结束时间排序activities.sort(key=lambda x: x[1])# 初始化last_end_time = 0selected_activities = []# 选择活动for start, end in activities:if start >= last_end_time:  # 与最后选定的活动不冲突selected_activities.append((start, end))last_end_time = endreturn selected_activities# 活动列表,每个元素是一个元组(开始时间,结束时间)
activities = [(0, 6), (3, 4), (1, 2), (5, 7), (8, 9), (5, 9)]# 调用函数
selected = activity_selection(activities)# 输出结果
print("Selected activities:", selected)
结果分析

        贪心策略是选择结束最早的活动,从而为后面尽可能多的活动留出时间。这种方法能够有效地最大化可以参加的活动数量。

结论

        贪心算法以其实现简单和在特定问题上的有效性而闻名。虽然它不总是能产生全局最优解,但在很多问题上,如找零问题和活动选择问题,它提供了非常高效的解决方案。在实际应用中,理解问题的结构和贪心算法的局限性是使用这种算法成功的关键。

        继续探索贪心算法的应用,我们可以考虑其他有趣的问题,比如压缩编码、图的顶点覆盖等,这些问题都可以通过贪心策略找到有效的解决方案,虽然可能不是最优解。

案例分析:霍夫曼编码

项目背景:霍夫曼编码是一种广泛使用的数据压缩方法。该算法基于字符出现频率构建最优前缀编码,频率高的字符使用较短的编码,频率低的字符使用较长的编码。

使用 Python 实现霍夫曼编码

        霍夫曼编码使用贪心策略从底部开始构建最优前缀编码树,每次合并最小的两个节点。

import heapq
from collections import Counter, namedtuple# 定义树节点,包含字符、频率、左子节点和右子节点
class Node(namedtuple("Node", ["freq", "char", "left", "right"])):def __lt__(self, other):return self.freq < other.freqdef huffman_encoding(s):# 统计字符频率if not s:return None, Nonefreq = Counter(s)# 使用优先队列(堆)构建森林forest = [Node(freq=frq, char=ch, left=None, right=None) for ch, frq in freq.items()]heapq.heapify(forest)# 合并森林中的树,直到只剩一个树while len(forest) > 1:left = heapq.heappop(forest)right = heapq.heappop(forest)merged = Node(left.freq + right.freq, None, left, right)heapq.heappush(forest, merged)# 生成编码def codes(node, prefix="", code={}):if node.char is not None:code[node.char] = prefix or '0'else:codes(node.left, prefix + '0', code)codes(node.right, prefix + '1', code)return codereturn codes(forest[0])# 示例字符串
s = "this is an example for huffman encoding"
codes = huffman_encoding(s)print("Character codes:")
for char, code in codes.items():print(f"{char}: {code}")
结果分析

        在这个案例中,通过构建一棵二叉树,并为每个字符分配一个独特的二进制码,霍夫曼编码提供了一种高效的数据压缩方法。此方法尤其适用于处理字符频率分布不均的情况。

案例分析:图的顶点覆盖

项目背景:在一个无向图中,顶点覆盖是一组顶点,使得图中的每条边至少有一个端点在此顶点集中。这是一个经典的NP完全问题。

使用 Python 实现顶点覆盖的贪心算法

        这个算法选择与最多边相连的顶点加入覆盖集,然后移除所有与这些顶点相连的边,重复此过程。

def greedy_vertex_cover(edges):cover = set()while edges:# 选择最多边相连的顶点v = max(set(sum(edges, ())), key=lambda x: sum(1 for e in edges if x in e))cover.add(v)# 移除所有与选择顶点相连的边edges = [e for e in edges if v not in e]return cover# 示例边集
edges = [(1, 2), (2, 3), (2, 4), (3, 4), (4, 5)]
cover = greedy_vertex_cover(list(edges))
print("Vertex cover:", cover)
结果分析

        贪心算法为图的顶点覆盖问题提供了一个近似解。虽然这种方法不保证最小覆盖,但通常能快速找到一个较好的解,尤其是在大规模图中。

结论

        贪心算法在各种场景下提供了一种简单且高效的解决方案策略。在实际应用中,尽管它可能不总是产生最优解,但由于其实现简单和在特定问题上的有效性,它被广泛用于解决实际问题,从数据压缩到资源分配等领域。对于需要快速可靠解决方案的情况,贪心算法是一个非常有用的工具。

        继续探讨贪心算法的应用,我们可以进一步考虑它在路线规划、调度、网络流和其他优化问题中的使用。这些问题常见于实际工程和科学研究中,贪心策略能够提供初步解决方案,常常作为更复杂算法的基础或启发式部分。

案例分析:最短路径问题

项目背景:最短路径问题是图论中的一个经典问题,目的是找到图中两个顶点之间的最短路径。Dijkstra算法是解决这个问题的一种贪心算法。

使用 Python 实现 Dijkstra 算法

        Dijkstra算法是基于贪心策略的:在每一步选择最小的未处理的顶点,并更新其邻居的最短路径。

import heapqdef dijkstra(graph, start):# 初始化距离表,所有节点的距离都设置为无限大distances = {vertex: float('infinity') for vertex in graph}distances[start] = 0# 优先队列,保存每个顶点的最短路径和顶点名priority_queue = [(0, start)]while priority_queue:# 选择距离最小的顶点current_distance, current_vertex = heapq.heappop(priority_queue)# 节点的距离如果被更新过,跳过处理if current_distance > distances[current_vertex]:continue# 访问每个邻接的点for neighbor, weight in graph[current_vertex].items():distance = current_distance + weight# 只有在找到更短的路径时才进行更新if distance < distances[neighbor]:distances[neighbor] = distanceheapq.heappush(priority_queue, (distance, neighbor))return distances# 图的表示:邻接表
graph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}start_vertex = 'A'
distances = dijkstra(graph, start_vertex)
print("Distances from start vertex:", distances)
结果分析

        Dijkstra 算法能够有效地解决最短路径问题,贪心策略在每一步选择距离最近的未处理顶点,确保了每次处理的都是当前可达的最短路径。

案例分析:任务调度问题

项目背景:在任务调度问题中,我们可能需要根据任务的紧急程度或持续时间来优先处理任务。一种常见的策略是使用最短处理时间优先(SPT)策略。

使用 Python 实现简单的任务调度
def schedule_tasks(tasks):# 按照任务持续时间排序tasks.sort(key=lambda x: x[1])  # 假设每个任务表示为(任务名, 持续时间)total_duration = 0schedule = []for task, duration in tasks:schedule.append((task, total_duration))total_duration += durationreturn scheduletasks = [('Task1', 3), ('Task2', 2), ('Task3', 6), ('Task4', 1)]
scheduled = schedule_tasks(tasks)
print("Task Schedule:", scheduled)
结果分析

        按最短处理时间优先策略调度任务,可以最小化任务的平均等待时间,这种贪心策略在单个或多个资源的任务调度中非常有效。

结论

        贪心算法在许多优化问题中提供了有效的解决策略,尤其适用于那些可以通过局部最优决策逐步达到全局最优的问题。在实际应用中,虽然这些算法可能不总能保证最优解,但它们的计算效率和实现简便性使它们成为许多情况下的首选方法。对于复杂的优化问题,贪心算法常常作为更复杂算法的一部分,或者在多阶段优化过程中起到关键作用。

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

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

相关文章

【Web前端】JavaScript—01

1.Javascript简介 简称JS&#xff0c;是当前最流行、应用最广泛的客户端脚本语言&#xff0c;用来在网页中添加一些动态效果与交互功能。在web开发领域有着举足轻重的地位。 2.JavaScript包含内容 核心ECMAScript(es):提供语言的语法和基本对象(数据类型、运算符、流程控制等…

Android Studio 之颜色

在Android中&#xff0c;颜色值由透明度alpha和RGB&#xff08;红、绿、蓝&#xff09;三原色定义&#xff0c;有八位十六进制数与六位十六进制数两种编码&#xff0c;例如八位编码FFEEDDCC&#xff0c;FF表示透明度&#xff0c;EE表示红色的浓度&#xff0c;DD表示绿色的浓度&…

Java特性之设计模式【代理模式】

一、代理模式 概述 在代理模式&#xff08;Proxy Pattern&#xff09;中&#xff0c;一个类代表另一个类的功能。这种类型的设计模式属于结构型模式 在代理模式中&#xff0c;我们创建具有现有对象的对象&#xff0c;以便向外界提供功能接口 主要解决&#xff1a; 在直接访问…

设计模式——外观模式(Facade)

外观模式&#xff08;Facade Pattern&#xff09; 是一种结构型设计模式&#xff0c;它为一个子系统中的一组接口提供一个统一的高层接口&#xff0c;使得子系统更加容易使用。这种类型的设计模式属于结构型模式&#xff0c;它向客户端提供了一个接口&#xff0c;隐藏了子系统的…

项目管理-项目资源管理2/2

项目管理&#xff1a;每天进步一点点~ 活到老&#xff0c;学到老 ヾ(◍∇◍)&#xff89;&#xff9e; 何时学习都不晚&#xff0c;加油 资源管理&#xff1a;6个过程“硅谷火箭管控” ①规划资源管理&#xff1a; 写计划 ②估算活动资源&#xff1a;估算团队资源&…

【代码随想录37期】Day01 二分查找 + 移除元素

二分查找 力扣704 贴一下之前的笔记&#xff1a; 没想到一下子写不出来&#xff0c;忘记什么是二分法了&#xff0c;这里回顾一下&#xff1a; 「二分查找 binary search」是一种基于分治策略的高效搜索算法。 它利用数据的有序性&#xff0c;每轮减少一半搜索范围&#xff…

Kafak 消费异常:The coordinator is not available.

Kafak 消费异常:The coordinator is not available. 1. 问题描述2. 问题排查2.1 Topic 状态异常2.2 `__consumer_offsets` 简介1. 问题描述 在新环境部署 Kafak 时,发现可以正常产生消息,但是无法正常消费消息,消费消息的异常日志如下: 11:59:53.315 [main] DEBUG org.a…

PPP点对点协议

概述 Point-to-Point Protocol&#xff0c;点到点协议&#xff0c;工作于数据链路层&#xff0c;在链路层上传输网络层协议前验证链路的对端&#xff0c;主要用于在全双工的同异步链路上进行点到点的数据传输。 PPP主要是用来通过拨号或专线方式在两个网络节点之间建立连接、…

docker-本地私有仓库、harbor私有仓库部署与管理

一、本地私有仓库&#xff1a; 1、本地私有仓库简介&#xff1a; docker本地仓库&#xff0c;存放镜像&#xff0c;本地的机器上传和下载&#xff0c;pull/push。 使用私有仓库有许多优点&#xff1a; 节省网络带宽&#xff0c;针对于每个镜像不用每个人都去中央仓库上面去下…

SQL查询语句(三)范围查找关键字

在上一篇文章中&#xff0c;我们介绍了SQL语句中&#xff0c;逻辑关键字的作用&#xff0c;并举例演示了如何用逻辑关键字来组合WHERE子句。在文章的末尾我们提到了两个用于范围查找的关键字IN和BETWEEN。这两个关键字都可以与NOT关键字灵活组合&#xff0c;起到对字句结果取反…

深度学习中模块化设计的理念优势

模块化设计在深度学习领域中是一个重要的概念&#xff0c;比如在构建和改进类似于编码器-解码器这样的复杂模型时&#xff0c;transformer就是编码器-解码器架构的一个实例。模块化设计可以帮助我们快速集成最新的研究成果&#xff0c;支持模型的快速迭代&#xff0c;这些都与深…

Jmeter用jdbc实现对数据库的操作

我们在用Jmeter进行数据库的操作时需要用到配置组件“JDBC Connection Configuration”&#xff0c;通过配置相应的驱动能够让我们通过Jmeter实现对数据库的增删改查&#xff0c;这里我用的mysql数据库一起来看下是怎么实现的吧。 1.驱动包安装 在安装驱动之前我们要先查看当前…

【刷题篇】双指针(二)

文章目录 1、有效三角形的个数2、查找总价格为目标值的两个商品3、三数之和4、四数之和 1、有效三角形的个数 给定一个包含非负整数的数组 nums &#xff0c;返回其中可以组成三角形三条边的三元组个数。 class Solution { public:int triangleNumber(vector<int>& n…

MQTT服务搭建及python使用示例

1、MQTT协议 1.1、MQTT介绍 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;是一种轻量级的、基于发布/订阅模式的通信协议&#xff0c;通常用于物联网设备之间的通讯。它具有低带宽、低功耗和开放性等特点&#xff0c;适合在网络带宽有限或者网络连接不稳定…

联发科天玑AI开发套件亮相:开发智能终端生成式AI应用的全面工具

在今日召开的天玑开发者大会2024&#xff08;MDDC 2024&#xff09;上&#xff0c;联发科向外界展示了其最新力作——天玑AI开发套件。该套件是为合作伙伴提供终端生成式AI应用开发的一站式工具包&#xff0c;意在简化并加速开发过程。 联发科推出的天玑AI开发套件包括四大核心…

去除图片水印软件-inpaint

一、普通使用教程 亲眼看看使用 Inpaint 从照片中删除不需要的元素是多么容易&#xff1a; 1.1加载图片 1.2 选择要纠正的问题区域 1.3 告别不需要的对象并保存 二、功能 1 修复旧照片 老并不总是意味着坏。我们拥有的一些旧照片对我们来说仍然很重要&#xff0c;因为它们仍…

leetcode 2266.统计打字方案数

思路&#xff1a;dp。 这道题其实也是爬楼梯的变形。 不过&#xff0c;这里需要分类讨论一下&#xff1a;就是选择7或者9的时候是4种递推情况&#xff0c;其他的都是3种。 而且&#xff0c;我们可以利用dp数组过程记录的特点运用在本题当中。 这里需要解决几个问题&#xf…

minio上传文件失败如何解决

1. 做了什么操作 通过接口上传excel文件&#xff0c;返回响应值 2. 错误如图 2. 如何解决 根据错误描述定位到了部署minio的地方minio通过docker部署&#xff0c;找到docker - compose发现配置文件中minio有两个端口&#xff0c;一个是用于api的&#xff0c;一个是用于管理界面…

Dell EMC Storage Unity: Remove/Install Memory Module

SP A 一个内存故障 点击system view -> Enclosures->Top查看 再次查看Alert&#xff0c; 确认内存出现问题 进入Service &#xff0c; 将SP A置为service状态 移出SP A &#xff0c;进行内存更换 更换完内存后&#xff0c;将SP A插入设备&#xff0c;并进行线缆连接 进入…

6层板学习笔记2

说明:笔记基于6层全志H3消费电子0.65MM间距BGA 67、多层板的电源建议直接大面积铺铜,不建议走线,铺铜充分满足其载流能力 68、凡亿推荐表层1OZ的铜厚线宽20MIL能承载1A的电流,内层0.5OZ的铜厚线宽为40MIL能承载1A的电流,过孔直径20MIL(0.5MM)能承载1A左右的电流,实际设…