在算法领域,贪心算法是一种简单而高效的解题策略。它通过在每一步选择局部最优解,以期达到全局最优解。掌握贪心策略,能让我们在解决某些问题时更加得心应手。本文将揭秘常见问题及实战技巧,帮助你轻松提升算法效率。
贪心算法的基本原理
贪心算法的核心思想是,在每一步选择中都采取当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的算法。它通常适用于以下几种情况:
- 最优子结构:问题的最优解包含其子问题的最优解。
- 贪心选择性质:通过局部最优的选择,可以逐步逼近全局最优解。
- 问题可被分解:问题可以被分解成若干个相互独立的小问题。
常见问题及实战技巧
1. 活动选择问题
问题描述:给定一系列活动,每个活动有一个开始时间和结束时间。选择一个最大子集,使得这些活动互不冲突。
贪心策略:按照结束时间排序,选择第一个不冲突的活动。
实战技巧:使用优先队列(如Java中的PriorityQueue)维护当前已选择活动的结束时间,遍历所有活动,若当前活动结束时间大于优先队列头部元素,则将其加入队列。
import java.util.PriorityQueue;
public class ActivitySelection {
public static void main(String[] args) {
int[] start = {1, 3, 0, 5, 8, 5};
int[] end = {2, 4, 6, 7, 9, 9};
PriorityQueue<Integer> pq = new PriorityQueue<>(Comparator.comparingInt(i -> end[i]));
for (int i = 0; i < end.length; i++) {
if (pq.isEmpty() || pq.peek() <= start[i]) {
pq.offer(end[i]);
}
}
while (!pq.isEmpty()) {
System.out.println(pq.poll());
}
}
}
2. 零钱兑换问题
问题描述:给定无限个面值为1、5、10、25的硬币,以及一个总金额n,求最少硬币个数。
贪心策略:优先使用面值最大的硬币。
实战技巧:从大到小遍历硬币面值,每次都尽量使用当前面值最大的硬币。
public class CoinChange {
public static int coinChange(int[] coins, int amount) {
Arrays.sort(coins);
int[] dp = new int[amount + 1];
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
dp[i] = Integer.MAX_VALUE;
for (int j = 0; j < coins.length; j++) {
if (coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
}
}
3. 最长不重复子串
问题描述:给定一个字符串,求最长的无重复字符子串的长度。
贪心策略:使用双指针遍历字符串,维护一个滑动窗口,记录当前窗口内的字符。
实战技巧:使用HashMap记录字符在字符串中的位置,若窗口内出现重复字符,则将左指针移动到重复字符位置之后。
public class LongestSubstring {
public static int lengthOfLongestSubstring(String s) {
int[] last = new int[128];
int ans = 0, start = -1;
for (int i = 0; i < s.length(); i++) {
int index = s.charAt(i);
start = Math.max(start, last[index] + 1);
ans = Math.max(ans, i - start + 1);
last[index] = i;
}
return ans;
}
}
总结
掌握贪心策略,能帮助我们高效解决一些算法问题。在实际应用中,要善于观察问题的特点,运用贪心算法的基本原理,结合实战技巧,才能取得更好的效果。希望本文能对你有所帮助。
