贪心算法 - Java实现面值问题两种策略寻找最优
1.贪心算法
1.1 贪心算法的介绍
- 贪婪算法(Greedy)的定义:是一种在每一步选中都采取在当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的算法
- 由于贪心算法的高效性以及所求得答案比较接近最优结果,贪心算法可以作为辅助算法或解决一些要求结果不特别精确的问题
1.2 面值问题
- 现在有许多面值不同的货币,我们遵循不同的策略来组合不定数量的货币来满足目标面值
- 常见的策略有如下两种:
- 最大面值策略:指先匹配面值大的货币,尽量用更少的货币来满足目标面值
- 最大数量策略:指尽量匹配更多数量的货币,也就是先匹配小面值货币来满足目标值
2.Java实现面值问题
2.1 最大面值策略
private int[] maxWeightStrategy(Integer[] newParentArray, int aim){
Arrays.sort(newParentArray, Collections.reverseOrder());
int result = 0;
LinkedList<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < newParentArray.length; i++){
if (result < aim && newParentArray[i] <= aim){
if (result + newParentArray[i] <= aim){
result += newParentArray[i];
linkedList.add(newParentArray[i]);
if (result == aim){
break;
}
}
} else {
break;
}
}
int[] resultArray = null;
if (result == aim){
resultArray = linkedList.stream().mapToInt(Integer::intValue).toArray();
}
return resultArray;
}
2.2 最大数量策略
private int[] maxNumStrategy(Integer[] newParentArray, int aim){
Arrays.sort(newParentArray);
int result = 0;
LinkedList<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < newParentArray.length; i++){
if (result < aim && newParentArray[i] <= aim){
if (result + newParentArray[i] <= aim){
if (i + 1 < newParentArray.length && result + newParentArray[i] + newParentArray[i + 1] <= aim){
if (result + newParentArray[i] + newParentArray[i + 1] == aim){
result += newParentArray[i];
result += newParentArray[i + 1];
linkedList.add(newParentArray[i]);
linkedList.add(newParentArray[i + 1]);
break;
} else {
result += newParentArray[i];
linkedList.add(newParentArray[i]);
}
} else {
for (int j = i + 1; j < newParentArray.length; j++){
if (result + newParentArray[j] == aim){
result += newParentArray[j];
linkedList.add(newParentArray[j]);
break;
}
}
}
if (result == aim){
break;
}
}
} else {
break;
}
}
int[] resultArray = null;
if (result == aim){
resultArray = linkedList.stream().mapToInt(Integer::intValue).toArray();
}
return resultArray;
}
2.3 完整代码
- 我们对外只暴露一个 API,通过 枚举类实现用户选择策略
package com.lagou.greedyMethod;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
public class GreedyMethod {
public enum GreedyStrategy{
MAX_NUM_Strategy,
MAX_WEIGHT_STRATEGY;
}
public int[] greedy(int[] parentArray, int aim, GreedyStrategy greedyStrategy){
int[] result = null;
if (parentArray == null) return result;
Integer[] newParentArray = new Integer[parentArray.length];
for (int i = 0; i < parentArray.length; i++){
newParentArray[i] = parentArray[i];
}
if (greedyStrategy == GreedyStrategy.MAX_NUM_Strategy){
result = maxNumStrategy(newParentArray, aim);
} else if (greedyStrategy == GreedyStrategy.MAX_WEIGHT_STRATEGY){
result = maxWeightStrategy(newParentArray, aim);
}
return result;
}
private int[] maxWeightStrategy(Integer[] newParentArray, int aim){
Arrays.sort(newParentArray, Collections.reverseOrder());
int result = 0;
LinkedList<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < newParentArray.length; i++){
if (result < aim && newParentArray[i] <= aim){
if (result + newParentArray[i] <= aim){
result += newParentArray[i];
linkedList.add(newParentArray[i]);
if (result == aim){
break;
}
}
} else {
break;
}
}
int[] resultArray = null;
if (result == aim){
resultArray = linkedList.stream().mapToInt(Integer::intValue).toArray();
}
return resultArray;
}
private int[] maxNumStrategy(Integer[] newParentArray, int aim){
Arrays.sort(newParentArray);
int result = 0;
LinkedList<Integer> linkedList = new LinkedList<>();
for (int i = 0; i < newParentArray.length; i++){
if (result < aim && newParentArray[i] <= aim){
if (result + newParentArray[i] <= aim){
if (i + 1 < newParentArray.length && result + newParentArray[i] + newParentArray[i + 1] <= aim){
if (result + newParentArray[i] + newParentArray[i + 1] == aim){
result += newParentArray[i];
result += newParentArray[i + 1];
linkedList.add(newParentArray[i]);
linkedList.add(newParentArray[i + 1]);
break;
} else {
result += newParentArray[i];
linkedList.add(newParentArray[i]);
}
} else {
for (int j = i + 1; j < newParentArray.length; j++){
if (result + newParentArray[j] == aim){
result += newParentArray[j];
linkedList.add(newParentArray[j]);
break;
}
}
}
if (result == aim){
break;
}
}
} else {
break;
}
}
int[] resultArray = null;
if (result == aim){
resultArray = linkedList.stream().mapToInt(Integer::intValue).toArray();
}
return resultArray;
}
}
2.4 进行测试
package com.lagou.greedyMethod.test;
import com.lagou.greedyMethod.GreedyMethod;
import java.util.Arrays;
public class GreedyMethodTest {
public static void main(String[] args) {
GreedyMethod greedyMethod = new GreedyMethod();
int[] parentArray = {3, 5, 6, 2, 7, 8, 1, 3, 9, 3, 4, 2 ,5};
int[] parentArray2 = {3, 5, 6, 2, 7, 8, 1, 3, 9, 3, 4, 2 ,5};
int[] greedy = greedyMethod.greedy(parentArray, 20, GreedyMethod.GreedyStrategy.MAX_NUM_Strategy);
System.out.println("最大数量策略:" + Arrays.toString(greedy));
int[] greedy1 = greedyMethod.greedy(parentArray2, 20, GreedyMethod.GreedyStrategy.MAX_WEIGHT_STRATEGY);
System.out.println("最大质量策略:" + Arrays.toString(greedy1));
}
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/0308357d2c5248d5b0a3f0f0ca7d99d2.png)
3.总结
- 时间复杂度
- 在不考虑排序的前提下,贪心算法只需要一次循环,所以时间复杂度是O(n)
- 优缺点
- 优点:性能高,能用贪心算法解决的往往是最优解
- 缺点:在实际情况下能用的不多,用贪心算法解的往往不是最好的