【贪心算法】什么是贪心算法

贪心算法(Greedy Algorithm)是一种在每一步决策中都采取当前状态下“看起来最好”的选择,从而希望最终得到全局最优解的算法思想。它不从整体最优上加以考虑,而是做出某种意义上的**局部最优选择**。

### 核心特点:
- **局部最优**:每一步都选择当前状态下的最优解。
- **不回溯**:一旦做出选择,就不会撤销或更改。
- **简单高效**:通常实现简单,时间复杂度较低。

### 举个简单例子:
假设你有若干张纸币,需要凑出 36 元,目标是用的纸币数量最少。纸币面额有:20 元、10 元、5 元、1 元。

贪心算法的做法是:
- 先选一张 20 元(剩下 16 元)
- 再选一张 10 元(剩下 6 元)
- 再选一张 5 元(剩下 1 元)
- 最后选一张 1 元(完成)

总共用了 4 张纸币,这是最优解。

### 但贪心算法并不总是能得到全局最优解:
比如,如果纸币面额是 25 元、20 元、1 元,要凑 40 元:
- 贪心算法会选一张 25 元(剩下 15 元)
- 然后选 15 张 1 元,总共用了 16 张
- 但最优解其实是选两张 20 元,只用 2 张

### 适用条件:
贪心算法只有在问题满足**贪心选择性质**和**最优子结构性质**时才能保证得到全局最优解。

- **贪心选择性质**:局部最优选择能导致全局最优。
- **最优子结构**:问题的最优解包含其子问题的最优解。

### 常见应用:
- 最小生成树(Prim、Kruskal)
- 哈夫曼编码
- 活动选择问题
- 最短路径的 Dijkstra 算法(在某些条件下)

总结一句话:  
**贪心算法就是“每一步都选眼前最好的”,但“眼光是否长远”决定了它是否靠谱。**

### Dijkstra算法中的贪心选择性质 Dijkstra算法利用了贪心算法的思想来寻找加权有向图中从单一源到其他顶点的最短路径。该算法通过逐步扩展已找到最短路径的节点集合,每次从未处理的节点中选取距离最近的一个加入此集合,并更新其邻居的距离估计值。 为了证明Dijkstra算法中的贪心选择性质,即在每一步选择当前未访问过的具有最小临时距离标记的顶点作为下一个要处理的对象是合理的,可以基于以下几点: #### 局部最优解等于全局最优解 当按照上述方式选择下一点时,实际上是在做一种局部上的最佳决策——挑选离起点最近的那个尚未被确认最短路径长度的结点v。由于任何一条通往终点u的有效路径都必然经过某些中间节点w,而这些中间节点要么已经被纳入S(已经计算出确切最短路径),要么还在Q(等待评估)。如果存在另一条更优路线,则意味着这条新发现的道路能够提供更低的成本到达某一个或多个这样的w;然而这与之前对于v的选择矛盾,因为这意味着应该先选这个成本更低的新候选者而不是v[^2]。 因此,在每一次迭代过程中所做的决定都是针对当时情况下的最好可能选项之一,而且这种做法最终会引导我们获得整个问题空间内的整体最优解决方案。 #### 无后效性的满足 另一个重要方面在于确保所采用的方法符合贪心策略的要求—特别是所谓的“无后效性”。具体来说就是指一旦某个特定阶段做出了抉择之后就不会再受到后续变化的影响。就本案例而言,每当一个新的顶点被正式接纳进入已完成部分(S)以后,它与其他剩余待考察位置之间的关系便固定下来不会再改变。换句话说,即使后来又发现了更好的途径通向那些地方也不会再去调整早前确立下来的结论。 综上所述,通过对以上两个条件的验证可以看出,Dijkstra算法确实遵循着有效的贪心原则来进行操作,从而保证了所得结果既快速又能达到预期效果。 ```python def dijkstra(graph, start): import heapq n = len(graph) dist = [float('inf')] * n visited = [False] * n prev = [-1] * n pq = [] dist[start] = 0 heapq.heappush(pq, (0, start)) while pq: d, u = heapq.heappop(pq) if visited[u]: continue visited[u] = True for v, weight in enumerate(graph[u]): if not visited[v] and weight != float('inf'): alt = dist[u] + weight if alt < dist[v]: dist[v] = alt prev[v] = u heapq.heappush(pq, (alt, v)) return dist, prev ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值