当前位置: 首页 > article >正文

python 实现贪心算法(Greedy Algorithm)

贪心算法(Greedy Algorithm)是一种在每一步选择中都采取当前最优的选择,希望通过局部最优解达到全局最优解的算法设计方法。以下是使用Python实现贪心算法解决几个经典问题的示例:


1. 活动选择问题(Activity Selection Problem)

活动选择问题是选择最多的互不冲突的活动。

def activity_selection(activities):
    # 按结束时间排序
    activities.sort(key=lambda x: x[1])
    selected = []
    last_end = -1
    
    for start, end in activities:
        if start >= last_end:
            selected.append((start, end))
            last_end = end
    
    return selected

# 示例
activities = [(1, 4), (3, 5), (0, 6), (5, 7), (3, 9), (5, 9), (6, 10), (8, 11), (8, 12), (2, 14), (12, 16)]
print(activity_selection(activities))
# 输出: [(1, 4), (5, 7), (8, 11), (12, 16)]

2. 霍夫曼编码(Huffman Coding)

霍夫曼编码是一种用于数据压缩的贪心算法。

import heapq

class HuffmanNode:
    def __init__(self, char, freq):
        self.char = char
        self.freq = freq
        self.left = None
        self.right = None
    
    def __lt__(self, other):
        return self.freq < other.freq

def build_huffman_tree(freq_map):
    heap = [HuffmanNode(char, freq) for char, freq in freq_map.items()]
    heapq.heapify(heap)
    
    while len(heap) > 1:
        left = heapq.heappop(heap)
        right = heapq.heappop(heap)
        merged = HuffmanNode(None, left.freq + right.freq)
        merged.left = left
        merged.right = right
        heapq.heappush(heap, merged)
    
    return heapq.heappop(heap)

def build_huffman_codes(node, prefix="", code_map=None):
    if code_map is None:
        code_map = {}
    if node:
        if node.char:
            code_map[node.char] = prefix
        build_huffman_codes(node.left, prefix + "0", code_map)
        build_huffman_codes(node.right, prefix + "1", code_map)
    return code_map

# 示例
freq_map = {'a': 5, 'b': 9, 'c': 12, 'd': 13, 'e': 16, 'f': 45}
huffman_tree = build_huffman_tree(freq_map)
huffman_codes = build_huffman_codes(huffman_tree)
print(huffman_codes)
# 输出: {'f': '0', 'c': '100', 'd': '101', 'a': '1100', 'b': '1101', 'e': '111'}

3. 最小生成树(MST, Minimum Spanning Tree)

最小生成树问题可以通过 Kruskal 或 Prim 算法解决。以下是 Kruskal 算法的实现。

class Graph:
    def __init__(self, vertices):
        self.V = vertices
        self.edges = []
    
    def add_edge(self, u, v, w):
        self.edges.append((u, v, w))
    
    def find(self, parent, i):
        if parent[i] == i:
            return i
        return self.find(parent, parent[i])
    
    def union(self, parent, rank, x, y):
        xroot = self.find(parent, x)
        yroot = self.find(parent, y)
        if rank[xroot] < rank[yroot]:
            parent[xroot] = yroot
        elif rank[xroot] > rank[yroot]:
            parent[yroot] = xroot
        else:
            parent[yroot] = xroot
            rank[xroot] += 1
    
    def kruskal_mst(self):
        result = []
        self.edges.sort(key=lambda x: x[2])  # 按权重排序
        parent = [i for i in range(self.V)]
        rank = [0] * self.V
        for u, v, w in self.edges:
            x = self.find(parent, u)
            y = self.find(parent, v)
            if x != y:
                result.append((u, v, w))
                self.union(parent, rank, x, y)
        return result

# 示例
g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)
print(g.kruskal_mst())
# 输出: [(2, 3, 4), (0, 3, 5), (0, 1, 10)]

4. 硬币找零问题(Coin Change Problem)

硬币找零问题是使用最少数量的硬币凑成指定金额。

def coin_change(coins, amount):
    coins.sort(reverse=True)  # 从大到小排序
    result = []
    for coin in coins:
        while amount >= coin:
            result.append(coin)
            amount -= coin
    return result if amount == 0 else None

# 示例
coins = [1, 2, 5, 10, 20, 50, 100, 500, 1000]
amount = 93
print(coin_change(coins, amount))
# 输出: [50, 20, 20, 2, 1]

总结

贪心算法的核心思想是每一步都选择当前最优的解,希望通过局部最优解达到全局最优解。然而,贪心算法并不总是能得到全局最优解,因此在使用时需要验证问题的性质是否适合贪心策略。


http://www.kler.cn/a/469149.html

相关文章:

  • Ubuntu下的小bug
  • reactor的Hooks.enableAutomaticContextPropagation();不生效解决方案
  • C++相关实验练习
  • 软件项目体系建设文档,项目开发实施运维,审计,安全体系建设,验收交付,售前资料(word原件)
  • 简述Linux的信号处理
  • SpringMVC(六)拦截器
  • 2025 年前端新技术如何塑造未来开发生态?
  • 解决CentOS 8 YUM源更新后报错问题:无法下载AppStream仓库元数据
  • SMMU软件指南之使用案例(Stage 2使用场景)
  • MySQL第四弹----数据库约束和数据库设计
  • 【连续学习之LwM算法】2019年CVPR顶会论文:Learning without memorizing
  • STM32拓展 低功耗案例1:睡眠模式 (register)
  • JavaScript系列(8)-- Array高级操作
  • javaEE-网络编程-3 UDP
  • LabVIEW 实现自动对焦的开发
  • 编译与汇编
  • kubelet状态错误报错
  • linux 逻辑卷挂盘
  • F.interpolate函数
  • [Linux]redis5.0.x升级至7.x完整操作流程
  • 使用MySQL APT源在Linux上安装MySQL
  • spring mvc源码学习笔记之五
  • 【华为OD-E卷 - 九宫格按键输入 100分(python、java、c++、js、c)】
  • Linux系统常用命令详解
  • 怎么找回电脑所有连接过的WiFi密码
  • 【论文阅读笔记】LTX-Video: Realtime Video Latent Diffusion