Python之贪心算法

Python实现贪心算法(Greedy Algorithm)

概念

贪心算法是一种在每一步选择中都采取当前状态下最优的选择,从而希望导致结果是全局最优的算法策略。

基本特点

  1. 局部最优选择:每一步都做出当前看起来最佳的选择
  2. 不可回退:一旦做出选择,就不可更改
  3. 高效性:通常比其他全局优化算法更快
  4. 不保证全局最优:但能得到近似最优解

基本实现框架

(以分数背包问题为栗子)

def greedy_algorithm(items, capacity):
    # 通常先按某种规则排序
    items.sort(key=lambda x: x[1]/x[0], reverse=True)
    #按单位重量价值(value/weight)降序排序
    
    total_value = 0 #背包中物品的总价值
    selected_items = [] #选择的物品列表(完整或部分物品)
    #开始选择
    for item in items:
        if capacity >= item[0]:
            capacity -= item[0]
            total_value += item[1]
            selected_items.append(item)
        else:
            # 可选: 部分物品的情况(如分数背包问题)
            fraction = capacity / item[0]
            total_value += item[1] * fraction
            selected_items.append((item[0]*fraction, item[1]*fraction))
            break
    
    return total_value, selected_items

经典应用示例 😍 😍

1. 找零钱问题

def coin_change(coins, amount):
    coins.sort(reverse=True)
    count = 0
    change = []
    
    for coin in coins:
        while amount >= coin:
            amount -= coin
            count += 1
            change.append(coin)
    
    return count if amount == 0 else -1, change

# 示例
coins = [25, 10, 5, 1]
print(coin_change(coins, 63))  # 输出: (6, [25, 25, 10, 1, 1, 1])

2. 区间调度问题

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

# 示例
intervals = [(1, 3), (2, 4), (3, 5), (4, 6)]
print(interval_scheduling(intervals))  # 输出: [(1, 3), (3, 5)]

3. 霍夫曼编码(数据压缩)

import heapq

def huffman_encoding(freq):
    heap = [[weight, [symbol, ""]] for symbol, weight in freq.items()]
    heapq.heapify(heap)
    
    while len(heap) > 1:
        lo = heapq.heappop(heap)
        hi = heapq.heappop(heap)
        for pair in lo[1:]:
            pair[1] = '0' + pair[1]
        for pair in hi[1:]:
            pair[1] = '1' + pair[1]
        heapq.heappush(heap, [lo[0] + hi[0]] + lo[1:] + hi[1:])
    
    return sorted(heapq.heappop(heap)[1:], key=lambda p: (len(p[-1]), p))

# 示例
freq = {'a': 5, 'b': 9, 'c': 12, 'd': 13, 'e': 16, 'f': 45}
print(huffman_encoding(freq))

适用场景

  1. 问题具有贪心选择性质:局部最优能导致全局最优
  2. 最优子结构:问题的最优解包含子问题的最优解
  3. 典型应用
    • 最小生成树(Prim和Kruskal算法)
    • 最短路径问题(Dijkstra算法)
    • 背包问题的分数版本
    • 任务调度问题
    • 文件压缩(霍夫曼编码)

贪心算法的局限性👀👀

  1. 不总是能得到全局最优解
  2. 需要证明问题的贪心选择性质
  3. 对某些问题可能需要结合其他算法(如动态规划)

贪心 vs 动态规划💪💪

特性贪心算法动态规划
决策每个阶段做局部最优选择考虑所有可能的子问题
复杂度通常更低通常更高
最优解保证不总是总是
存储需求通常更少需要存储子问题结果
典型问题找零钱、任务调度背包问题、最长子序列

总结

贪心算法因其高效性在实际工程中应用广泛,但使用时需要仔细分析问题是否适合贪心策略。😼😼

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值