Python贪心算法案例如何实现?

wen python案例 1

本文目录导读:

  1. 找零钱问题(最基础)
  2. 活动选择问题
  3. 背包问题(分数背包)
  4. 霍夫曼编码
  5. 任务调度问题
  6. 关键实现要点
  7. 贪心算法适用条件

我来用几个经典案例详细解释Python贪心算法的实现:

找零钱问题(最基础)

def make_change(amount, coins):
    """
    用最少的硬币找零
    贪心策略:每次选择面值最大的硬币
    """
    coins.sort(reverse=True)  # 从大到小排序
    change = []
    for coin in coins:
        while amount >= coin:
            amount -= coin
            change.append(coin)
    if amount == 0:
        return change
    else:
        return None  # 无法找零
# 测试
amount = 63
coins = [1, 5, 10, 25]  # 常见硬币面值
result = make_change(amount, coins)
print(f"找零 {amount} 元:{result}")  # [25, 25, 10, 1, 1, 1]

活动选择问题

def activity_selection(activities):
    """
    选择最多不重叠的活动
    贪心策略:每次选择结束时间最早的活动
    活动格式:(开始时间, 结束时间)
    """
    # 按结束时间排序
    activities.sort(key=lambda x: x[1])
    selected = [activities[0]]  # 第一个活动一定选择
    last_end = activities[0][1]
    for start, end in activities[1:]:
        if start >= last_end:  # 不重叠
            selected.append((start, end))
            last_end = end
    return selected
# 测试
activities = [(1, 3), (2, 5), (3, 7), (5, 9), (6, 10), (8, 11)]
result = activity_selection(activities)
print(f"选择的活动:{result}")  # [(1, 3), (3, 7), (8, 11)]

背包问题(分数背包)

def fractional_knapsack(items, capacity):
    """
    分数背包问题:物品可以分割
    贪心策略:按单位重量价值从高到低选择
    物品格式:(重量, 价值)
    """
    # 计算单位价值并按降序排序
    items_with_ratio = []
    for weight, value in items:
        ratio = value / weight
        items_with_ratio.append((weight, value, ratio))
    items_with_ratio.sort(key=lambda x: x[2], reverse=True)
    total_value = 0
    selected_items = []
    for weight, value, ratio in items_with_ratio:
        if capacity >= weight:
            # 整个物品放入
            total_value += value
            selected_items.append((weight, value, 1.0))
            capacity -= weight
        else:
            # 放入部分
            fraction = capacity / weight
            total_value += value * fraction
            selected_items.append((weight, value, fraction))
            break
    return total_value, selected_items
# 测试
items = [(10, 60), (20, 100), (30, 120)]
capacity = 50
total_value, selected = fractional_knapsack(items, capacity)
print(f"最大价值:{total_value}")
print(f"选择的物品(重量,价值,比例):{selected}")

霍夫曼编码

import heapq
from collections import Counter
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 huffman_encoding(text):
    """
    霍夫曼编码:最优前缀编码
    贪心策略:每次合并频率最小的两个节点
    """
    if not text:
        return "", {}
    # 统计字符频率
    freq = Counter(text)
    # 创建优先队列
    heap = [HuffmanNode(char, freq[char]) for char in freq]
    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)
    # 生成编码表
    codes = {}
    def generate_codes(node, code=""):
        if node:
            if node.char:  # 叶子节点
                codes[node.char] = code
            else:  # 内部节点
                generate_codes(node.left, code + "0")
                generate_codes(node.right, code + "1")
    generate_codes(heap[0])
    # 编码文本
    encoded_text = "".join(codes[char] for char in text)
    return encoded_text, codes
# 测试
text = "hello world"
encoded, codes = huffman_encoding(text)
print(f"原始文本:{text}")
print(f"编码表:{codes}")
print(f"编码结果:{encoded}")
print(f"压缩率:{len(encoded) / (len(text) * 8):.2%}")

任务调度问题

def task_scheduling(tasks):
    """
    任务调度:最小化延迟时间
    贪心策略:按截止时间排序,先做截止时间早的任务
    任务格式:(任务名, 处理时间, 截止时间)
    """
    # 按截止时间排序
    tasks.sort(key=lambda x: x[2])
    current_time = 0
    schedule = []
    max_lateness = 0
    for name, processing_time, deadline in tasks:
        start_time = current_time
        finish_time = current_time + processing_time
        # 计算延迟
        lateness = max(0, finish_time - deadline)
        max_lateness = max(max_lateness, lateness)
        schedule.append((name, start_time, finish_time, lateness))
        current_time = finish_time
    return schedule, max_lateness
# 测试
tasks = [
    ("Task A", 3, 5),
    ("Task B", 2, 4),
    ("Task C", 4, 8),
    ("Task D", 1, 3)
]
schedule, max_lateness = task_scheduling(tasks)
print("任务调度表:")
for name, start, finish, lateness in schedule:
    print(f"  {name}: 开始={start}, 结束={finish}, 延迟={lateness}")
print(f"最大延迟:{max_lateness}")

关键实现要点

  1. 排序:大多数贪心算法需要先对数据排序
  2. 局部最优:每一步选择当前最优解
  3. 不可回溯:一旦做出选择就不能改变

贪心算法适用条件

  • 最优子结构:问题的最优解包含子问题的最优解
  • 贪心选择性质:通过局部最优选择能得到全局最优解

这些案例覆盖了贪心算法的常见应用场景,可以根据实际需求进行调整和扩展。

标签: Python案例

抱歉,评论功能暂时关闭!