贪心算法是一种通过每一步的局部最优选择来寻找整体最优解的方法。在每个步骤中,贪心算法选择当前状态下的最佳选项,而不考虑未来可能的影响。尽管它不能保证一定能找到全局最优解,但贪心算法通常简单且高效,适用于许多实际问题。
贪心算法是一种寻找全局最优解的方法,其核心原理可概括为以下步骤:
问题建模:将问题分解成一系列子问题,每个子问题都有一定的优先级。
选择策略:在每个步骤中,选择当前子问题的最佳选项,即局部最优解,而不考虑未来可能的影响。
更新状态:根据所选策略,更新问题的状态以反映已经做出的选择。
重复:反复执行步骤2和步骤3,直到达到问题的终止条件。
贪心算法具有以下优势:
以下是四个经典问题,以及它们的贪心算法解决方案的示例:
问题描述:给定不同面额的硬币 coins 和一个总金额 amount,编写一个函数来计算可以凑成总金额所需的最少的硬币个数。
Python 示例
def coinChange(coins, amount):
coins.sort(reverse=True)
count = 0
for coin in coins:
while amount >= coin:
amount -= coin
count += 1
return count if amount == 0 else -1
Java 示例
public int coinChange(int[] coins, int amount) {
Arrays.sort(coins);
int count = 0;
for (int i = coins.length - 1; i >= 0; i--) {
while (amount >= coins[i]) {
amount -= coins[i];
count++;
}
}
return amount == 0 ? count : -1;
}
问题描述:给定一组物品,每个物品都有自己的重量和价值,以及一个容量限制的背包。目标是找到将哪些物品放入背包,可以使得背包中的物品总价值最大。
Python 示例:
def knapsack(values, weights, capacity):
n = len(values)
items = [(values[i], weights[i]) for i in range(n)]
items.sort(key=lambda x: x[1] / x[0], reverse=True)
total_value = 0
for item in items:
if capacity >= item[1]:
total_value += item[0]
capacity -= item[1]
return total_value
Java 示例
public int knapsack(int[] values, int[] weights, int capacity) {
int n = values.length;
Item[] items = new Item[n];
for (int i = 0; i < n; i++) {
items[i] = new Item(values[i], weights[i]);
}
Arrays.sort(items, (a, b) -> Double.compare(b.valuePerWeight, a.valuePerWeight));
int totalValue = 0;
for (Item item : items) {
if (capacity >= item.weight) {
totalValue += item.value;
capacity -= item.weight;
}
}
return totalValue;
}
class Item {
int value;
int weight;
double valuePerWeight;
Item(int value, int weight) {
this.value = value;
this.weight = weight;
valuePerWeight = (double) value / weight;
}
}
问题描述:给定一个连通的带权无向图,目标是找到一棵生成树,使得其包含所有顶点并且总权值最小。
Python 示例
class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = []
def add_edge(self, u, v, w):
self.graph.append([u, v, w])
def kruskal_mst(self):
result = []
self.graph = sorted(self.graph, key=lambda item: item[2])
parent = []
rank = []
def find(i):
if parent[i] == i:
return i
return find(parent[i])
def union(i, j):
i_root = find(i)
j_root = find(j)
if i_root != j_root:
if rank[i_root] < rank[j_root]:
parent[i_root] = j_root
elif rank[i_root] > rank[j_root]:
parent[j_root] = i_root
else:
parent[j_root] = i_root
rank[i_root] += 1
for node in range(self.V):
parent.append(node)
rank.append(0)
i = 0
e = 0
while e < self.V - 1:
u, v, w = self.graph[i]
i += 1
x = find(u)
y = find(v)
if x != y:
e += 1
result.append([u, v, w])
union(x, y)
minimum_cost = 0
for u, v, weight in result:
minimum_cost += weight
print(f"Edge ({u}-{v}) Weight: {weight}")
print(f"Minimum Spanning Tree Weight: {minimum_cost}")
# 创建一个带权无向图
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)
# 执行Kruskal算法找到最小生成树
g.kruskal_mst()
Java 示例
import java.util.*;
class Graph {
private int V, E;
private List edges;
static class Edge {
int src, dest, weight;
Edge(int src, int dest, int weight) {
this.src = src;
this.dest = dest;
this.weight = weight;
}
}
Graph(int V, int E) {
this.V = V;
this.E = E;
edges = new ArrayList<>();
}
void addEdge(int src, int dest, int weight) {
edges.add(new Edge(src, dest, weight));
}
int kruskalMST() {
int result = 0;
edges.sort(Comparator.comparingInt(e -> e.weight));
int[] parent = new int[V];
Arrays.fill(parent, -1);
int edgeCount = 0;
for (Edge edge : edges) {
int srcParent = find(parent, edge.src);
int destParent = find(parent, edge.dest);
if (srcParent != destParent) {
result += edge.weight;
parent[srcParent] = destParent;
edgeCount++;
}
if (edgeCount == V - 1) break;
}
return result;
}
private int find(int[] parent, int node) {
if (parent[node] == -1) return node;
return find(parent, parent[node]);
}
}
public class MinimumSpanningTree {
public static void main(String[] args) {
Graph graph = new Graph(4, 5);
graph.addEdge(0, 1, 10);
graph.addEdge(0, 2, 6);
graph.addEdge(0, 3, 5);
graph.addEdge(1, 3, 15);
graph.addEdge(2, 3, 4);
int minWeight = graph.kruskalMST();
System.out.println("Minimum Spanning Tree Weight: " + minWeight);
}
}
问题描述:给定一组字符及其出现频率,目标是构建一种前缀编码,使得出现频率高的字符具有较短的编码。
Python 示例
import heapq
from collections import defaultdict
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(chars, freq):
heap = [HuffmanNode(char, freq) for char, freq in zip(chars, freq)]
heapq.heapify(heap)
while len(heap) > 1:
left = heapq.heappop(heap)
right = heapq.heappop(heap)
merged = HuffmanNode('$', left.freq + right.freq)
merged.left = left
merged.right = right
heapq.heappush(heap, merged)
return heap[0]
def print_huffman_codes(node, code=""):
if node is None:
return
if node.char != '$':
print(f"Character: {node.char}, Code: {code}")
print_huffman_codes(node.left, code + "0")
print_huffman_codes(node.right, code + "1")
# 给定字符和频率数据
chars = ['a', 'b', 'c', 'd', 'e', 'f']
freq = [5, 9, 12, 13, 16, 45]
# 构建Huffman编码树
root = build_huffman_tree(chars, freq)
# 打印Huffman编码
print_huffman_codes(root)
Java 示例
import java.util.*;
class HuffmanNode {
char data;
int frequency;
HuffmanNode left, right;
HuffmanNode(char data, int frequency) {
this.data = data;
this.frequency = frequency;
left = right = null;
}
}
public class HuffmanCoding {
public static void main(String[] args) {
char[] chars = {'a', 'b', 'c', 'd', 'e', 'f'};
int[] freq = {5, 9, 12, 13, 16, 45};
HuffmanNode root = buildHuffmanTree(chars, freq);
printHuffmanCodes(root, "");
}
public static HuffmanNode buildHuffmanTree(char[] chars, int[] freq) {
PriorityQueue queue = new PriorityQueue<>(Comparator.comparingInt(node -> node.frequency));
for (int i = 0; i < chars.length; i++) {
queue.add(new HuffmanNode(chars[i], freq[i]));
}
while (queue.size() > 1) {
HuffmanNode left = queue.poll();
HuffmanNode right = queue.poll();
HuffmanNode newNode = new HuffmanNode('$', left.frequency + right.frequency);
newNode.left = left;
newNode.right = right;
queue.add(newNode);
}
return queue.poll();
}
public static void printHuffmanCodes(HuffmanNode node, String code) {
if (node == null) {
return;
}
if (node.data != '$') {
System.out.println("Character: " + node.data + ", Code: " + code);
}
printHuffmanCodes(node.left, code + "0");
printHuffmanCodes(node.right, code + "1");
}
}