贪心算法 - Java实现面值问题两种策略寻找最优

贪心算法 - Java实现面值问题两种策略寻找最优

1.贪心算法

1.1 贪心算法的介绍

  • 贪婪算法(Greedy)的定义:是一种在每一步选中都采取在当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的算法
  • 由于贪心算法的高效性以及所求得答案比较接近最优结果,贪心算法可以作为辅助算法或解决一些要求结果不特别精确的问题

1.2 面值问题

  • 现在有许多面值不同的货币,我们遵循不同的策略来组合不定数量的货币来满足目标面值
  • 常见的策略有如下两种:
    • 最大面值策略:指先匹配面值大的货币,尽量用更少的货币来满足目标面值
    • 最大数量策略:指尽量匹配更多数量的货币,也就是先匹配小面值货币来满足目标值

2.Java实现面值问题

2.1 最大面值策略

// 最大质量策略
    private int[] maxWeightStrategy(Integer[] newParentArray, int aim){
        // 默认排序是升序,使用 Collections 可以改为降序的
        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;

/**
 * @author 云梦归遥
 * @date 2022/5/21 19:03
 * @description 贪心算法 - 背包问题
 */
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; // 空数组,直接返回 null
        // 将基本数组转化为 Integer 数组
        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){
        // 默认排序是升序,使用 Collections 可以改为降序的
        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;

/**
 * @author 云梦归遥
 * @date 2022/5/21 20:11
 * @description
 */
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));
    }
}

在这里插入图片描述

3.总结

  • 时间复杂度
    • 在不考虑排序的前提下,贪心算法只需要一次循环,所以时间复杂度是O(n)
  • 优缺点
    • 优点:性能高,能用贪心算法解决的往往是最优解
    • 缺点:在实际情况下能用的不多,用贪心算法解的往往不是最好的
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值