贪心算法(又称贪婪算法),核心思想在求解问题的时候,总是选择当前情况的最优解。贪心算法不是所有问题都能得到整体最优解,核心在于贪心算法的策略选择,选择的贪心策略需要具备无后效性,即某个状态以前的过程不能影响以后的状态至于当前状态有关。
贪心算法总是选择当前情况下的最优选择,而不是从整体最优考虑。贪心算法是做的局部最优选择,最终的结果可能在整体环境下不是最优解,但非常接近最优解。贪心算法也会因为策略不同得到不同的结果。
假设存在下面需要付费的广播台,以及广播台信号可以覆盖的地区。 如何选择最少的广播台,让所有的地区都可以接收到信号
public class GreedyAlgorithm {
public static void main(String[] args) {
//创建广播电台,放入到Map
HashMap<String, HashSet<String>> broadcasts = new HashMap<String, HashSet<String>>();
//将各个电台放入到broadcasts
HashSet<String> hashSet1 = new HashSet<String>();
hashSet1.add("北京");
hashSet1.add("上海");
hashSet1.add("天津");
HashSet<String> hashSet2 = new HashSet<String>();
hashSet2.add("广州");
hashSet2.add("北京");
hashSet2.add("深圳");
HashSet<String> hashSet3 = new HashSet<String>();
hashSet3.add("成都");
hashSet3.add("上海");
hashSet3.add("杭州");
HashSet<String> hashSet4 = new HashSet<String>();
hashSet4.add("上海");
hashSet4.add("天津");
HashSet<String> hashSet5 = new HashSet<String>();
hashSet5.add("杭州");
hashSet5.add("大连");
//加入到map
broadcasts.put("K1", hashSet1);
broadcasts.put("K2", hashSet2);
broadcasts.put("K3", hashSet3);
broadcasts.put("K4", hashSet4);
broadcasts.put("K5", hashSet5);
// 获取所有的地区集合
Set<String> allAreas = new HashSet<>();
for (HashSet<String> value : broadcasts.values()) {
allAreas.addAll(value);
}
// 定义一个maxKey指针 指向当前覆盖了最多未覆盖地区的Key
String maxKey = null;
// 定义一个临时set用于暂存key中覆盖的电台
Set<String> tempSet = new HashSet<>();
// 定义一个list 用于保存求解的电台结果
List<String> selector = new ArrayList<>();
while (allAreas.size() > 0) {
// 遍历所有的key 确定maxKey的值
for (String key : broadcasts.keySet()) {
tempSet.clear();
tempSet.addAll(broadcasts.get(key));
tempSet.retainAll(allAreas);
// 如果maxKey为空直接指向当前key集合
if (maxKey == null) {
maxKey = key;
} else {
// 如果maxKey不为空 需要判断 maxKey所覆盖的区域 如果比当前key覆盖的区域还要少 一定maxKey指向当前电台
broadcasts.get(maxKey).retainAll(allAreas);
// 当心算法的核心 一直判断当前的交集个数是不是大于 之前maxKey的交集个数 如果是则将maxKey重新赋值
if (tempSet.size() > broadcasts.get(maxKey).size()) {
maxKey = key;
}
}
}
// 确定了maxKey之后从allAreas中移除已经选择了的地区
if (maxKey != null) {
selector.add(maxKey);
allAreas.removeAll(broadcasts.get(maxKey));
// 重置maxKey
maxKey = null;
}
}
System.out.println(selector);
}
}
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。
注意:你不能在买入股票前卖出股票。
public class MaxProfit121 {
public static void main(String[] args) {
int[] input = {7, 1, 5, 3, 6, 4};
System.out.println(maxProfit(input));
}
public static int maxProfit(int[] prices) {
if (prices.length == 0) return 0;
int min = prices[0];
int maxProfit = 0;
for (int i = 0; i < prices.length; i++) {
int price = prices[i];
if (min > price) {
// 贪心思想 每次取最小
min = price;
} else {
// 贪心思想 每次取最大
maxProfit = Math.max(price - min, maxProfit);
}
}
return maxProfit;
}
}
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
**注意:**你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
public static int maxProfit(int[] prices) {
int maxProfit = 0;
if (prices.length <= 1) return maxProfit;
for (int i = 1; i < prices.length; i++) {
if (prices[i] > prices[i - 1]) maxProfit += (prices[i] - prices[i - 1]);
}
return maxProfit;
}
假定矩阵dp横坐标为第i天的股票 纵坐标为 买或者卖股票的最大收益 0 为卖掉股票 1为买股票
7 | 6 | 4 | 3 | 1 | |
---|---|---|---|---|---|
卖0 | 0 | 0>6-7=-1=>0 | 0>4-6 =>0 | 0>3-4 =>0 | 0>1-3 =>0 |
买1 | -7 | -6 | -4 | -3 | -1 |
最终结果为0
7 | 1 | 5 | 3 | 6 | 4 | |
---|---|---|---|---|---|---|
卖0 | 0 | 0 > 1-7 => 0 | 0<5-1=4 => 4 | 4>3-1 => 4 | 4<6+1 =>7 | 7> 4+1 =>7 |
买1 | -7 | -1 | -1>0-5 => -1 | -1 < 4-3=>1 | 1 > 4-6 =>1 | 1<7-4=>3 |
最大收益为7
买股票的最大收益为 上次交易的最大收益 - 当前股票价格 转成状态方程为 max(dp(i-1,0),dp(i-1,1)-prices[i])
买ath.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
public class MaxProfit122ByDynamic {
public static void main(String[] args) {
int[] prices = {7, 6, 4, 3, 1};
System.out.println(maxProfit(prices));
}
public static int maxProfit(int[] prices) {
int len = prices.length;
if (len < 2) {
return 0;
}
// 0 卖股票
// 1 买股票
/** 1 2 3 4 5
* 卖0 0 2-1 3-1
* 买1 -1 -1 -1
* 状态转移方程 收益 int[i][0] = max(int[i-1][0], prices[i] + int[i-1][1]) # 收入减去最低支出 现在支出是负数 所以需要+
* 支出 int[i][1] = max(int[i-1][0],int[i-1][0] - prices[i]) # 上一次的收入减去当前股票的支出
*/
int[][] dp = new int[prices.length][2];
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i = 1; i < dp.length; i++) {
dp[i][0] = Math.max(dp[i - 1][0], prices[i] + dp[i - 1][1]);
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
}
return dp[prices.length - 1][0];
}
}