美文网首页
数据结构之贪心算法

数据结构之贪心算法

作者: david161 | 来源:发表于2022-05-10 08:30 被阅读0次

    概念

    贪婪算法(Greedy)的定义:是一种在每一步选中都采取在当前状态下最好或最优的选择,从而希望导致结果是全局最好或最优的算法。
    贪婪算法:当下做局部最优判断,不能回退
    (能回退的是回溯,最优+回退是动态规划)
    由于贪心算法的高效性以及所求得答案比较接近最优结果,贪心算法可以作为辅助算法或解决一些要求
    结果不特别精确的问题
    注意:当下是最优的,并不一定全局是最优的。举例如下:


    image.png

    有硬币分值为10、9、4若干枚,问如果组成分值18,最少需要多少枚硬币?
    采用贪心算法,选择当下硬币分值最大的:10
    18-10=8
    8/4=2
    即:1个10、2个4,共需要3枚硬币
    实际上我们知道,选择分值为9的硬币,2枚就够了
    18/9=2
    如果改成:


    image.png
    有硬币分值为10、5、1若干枚,问如果组成分值16,最少需要多少枚硬币?
    采用贪心算法,选择当下硬币分值最大的:10
    16-10=6
    6-5=1
    即:1个10,1个5,1个1 ,共需要3枚硬币
    即为最优解
    由此可以看出贪心算法适合于一些特殊的情况,如果能用一定是最优解

    经典问题:部分背包

    背包问题是算法的经典问题,分为部分背包和0-1背包,主要区别如下:
    部分背包:某件物品是一堆,可以带走其一部分
    0-1背包:对于某件物品,要么被带走(选择了它),要么不被带走(没有选择它),不存在只带走一部分的情况。
    部分背包问题可以用贪心算法求解,且能够得到最优解。
    假设一共有N件物品,第 i 件物品的价值为 Vi ,重量为Wi,一个小偷有一个最多只能装下重量为W的背包,他希望带走的物品越有价值越好,可以带走某件物品的一部分,请问:他应该选择哪些物品?
    假设背包可容纳50Kg的重量,物品信息如下表:


    image.png
    贪心算法的关键是贪心策略的选择

    将物品按单位重量 所具有的价值排序。总是优先选择单位重量下价值最大的物品
    按照我们的贪心策略,单位重量的价值排序: 物品A > 物品B > 物品C
    因此,我们尽可能地多拿物品A,直到将物品1拿完之后,才去拿物品B,然后是物品C 可以只拿一部分.....

    package com.david.alth.greedy;
    
    /**
    * 贪心算法:部分背包 
    */ 
    public class BagDemo1 { 
        double bag; 
        public void take(Goods[] goodslist) { 
            // 对物品按照价值排序从高到低 
            Goods[] goodslist2 = sort(goodslist); 
            double sum_w = 0; 
            //取出价值最高的 
            for (int i = 0; i < goodslist2.length; i++) { 
                sum_w += goodslist2[i].weight; 
                if (sum_w <= bag) { 
                    System.out.println(goodslist2[i].name + "取" + goodslist2[i].weight +"kg"); 
                }else{
                    System.out.println(goodslist2[i].name + "取" +(bag-(sum_w- goodslist2[i].weight)) +"kg"); return ; 
                } 
            } 
        }
        
        // 按物品的每kg 价值排序 由高到低 price/weight 
        private Goods[] sort(Goods[] goodslist) {
            return goodslist; 
        }
        
        public static void main(String[] args) { 
            BagDemo1 bd = new BagDemo1(); 
            Goods goods1 = new Goods("A", 10, 60); 
            Goods goods2 = new Goods("B", 20, 100); 
            Goods goods3 = new Goods("C", 30, 120); 
            
            Goods[] goodslist = {goods1, goods2, goods3}; 
            bd.bag = 50; bd.take(goodslist);
        } 
    }
    
    public class Goods { 
        String name; 
        double weight; 
        double price; 
        double val; 
        
        public Goods(String name,double weight, double price) { 
            this.name=name; 
            this.weight = weight; 
            this.price = price; 
            val=price/weight;
        } 
    }
    
    时间复杂度

    在不考虑排序的前提下,贪心算法只需要一次循环,所以时间复杂度是O(n)

    优缺点

    优点:性能高,能用贪心算法解决的往往是最优解
    缺点:在实际情况下能用的不多,用贪心算法解的往往不是最好的

    适用场景

    针对一组数据,我们定义了限制值和期望值,希望从中选出几个数据,在满足限制值的情况下,期望值最大。
    每次选择当前情况下,在对限制值同等贡献量的情况下,对期望值贡献最大的数据(局部最优而全局最优)
    大部分能用贪心算法解决的问题,贪心算法的正确性都是显而易见的,也不需要严格的数学推导证明
    在实际情况下,用贪心算法解决问题的思路,并不总能给出最优解

    相关文章

      网友评论

          本文标题:数据结构之贪心算法

          本文链接:https://www.haomeiwen.com/subject/ccihurtx.html