贪心算法简单介绍

贪心算法是一种在每一步选择中都采取当前状态下最优或最优近似的选择,以期望最终得到全局最优解的算法。贪心算法并不总能得到全局最优解,但在某些问题上,它可以得到全局最优解,并且比动态规划等其他方法更为简单和高效。

贪心算法的基本思想

贪心算法的核心思想是:

  1. 贪心选择性质:每一步都做出局部最优选择,即当前最优的选择,希望通过一系列局部最优选择能得到全局最优解。
  2. 无后效性:当前的选择不会影响后续的选择,即后面的选择不依赖于之前的状态。

贪心算法的应用场景

贪心算法通常用于解决一些优化问题,比如最短路径问题、背包问题、活动选择问题、最小生成树等。下面通过几个经典问题来介绍贪心算法。

1. 活动选择问题

问题描述

给定一组活动,每个活动有一个开始时间和结束时间。要求选择尽可能多的活动,使得这些活动互不冲突。

贪心策略

每次选择结束时间最早且不与已选活动冲突的活动。

代码实现
java 复制代码
import java.util.Arrays;
import java.util.Comparator;

public class ActivitySelection {
    static class Activity {
        int start, end;

        Activity(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }

    public static void main(String[] args) {
        Activity[] activities = {
            new Activity(1, 4),
            new Activity(3, 5),
            new Activity(0, 6),
            new Activity(5, 7),
            new Activity(3, 9),
            new Activity(5, 9),
            new Activity(6, 10),
            new Activity(8, 11),
            new Activity(8, 12),
            new Activity(2, 14),
            new Activity(12, 16)
        };

        Arrays.sort(activities, Comparator.comparingInt(a -> a.end));

        int count = 1;
        int endTime = activities[0].end;

        for (int i = 1; i < activities.length; i++) {
            if (activities[i].start >= endTime) {
                count++;
                endTime = activities[i].end;
            }
        }

        System.out.println("Maximum number of activities: " + count);
    }
}

2. 0/1 背包问题的贪心近似

问题描述

给定一个容量为 W 的背包和 N 个物品,每个物品有一个重量和价值。要求在不超过背包容量的情况下,选择若干物品使得这些物品的总价值最大。

贪心策略

按单位价值(价值/重量)从大到小的顺序选择物品,尽量多地选择高单位价值的物品。

代码实现
java 复制代码
import java.util.Arrays;
import java.util.Comparator;

public class FractionalKnapsack {
    static class Item {
        int weight;
        int value;

        Item(int weight, int value) {
            this.weight = weight;
            this.value = value;
        }
    }

    public static void main(String[] args) {
        Item[] items = {
            new Item(10, 60),
            new Item(20, 100),
            new Item(30, 120)
        };
        int capacity = 50;

        Arrays.sort(items, Comparator.comparingDouble(i -> (double) i.value / i.weight).reversed());

        double totalValue = 0;
        int remainingCapacity = capacity;

        for (Item item : items) {
            if (item.weight <= remainingCapacity) {
                totalValue += item.value;
                remainingCapacity -= item.weight;
            } else {
                totalValue += item.value * ((double) remainingCapacity / item.weight);
                break;
            }
        }

        System.out.println("Maximum value in Knapsack = " + totalValue);
    }
}

3. 哈夫曼编码

问题描述

给定一组字符及其出现的频率,要求构建一棵二叉树,使得树的带权路径长度最小。带权路径长度是所有叶子节点的深度乘以频率之和。

贪心策略

每次选择频率最小的两个节点合并,直到所有节点合并成一棵树。

代码实现
java 复制代码
import java.util.PriorityQueue;

public class HuffmanCoding {
    static class Node {
        int freq;
        Node left, right;

        Node(int freq) {
            this.freq = freq;
        }
    }

    public static void main(String[] args) {
        int[] frequencies = {5, 9, 12, 13, 16, 45};

        PriorityQueue<Node> pq = new PriorityQueue<>(Comparator.comparingInt(n -> n.freq));

        for (int freq : frequencies) {
            pq.add(new Node(freq));
        }

        while (pq.size() > 1) {
            Node left = pq.poll();
            Node right = pq.poll();
            Node merged = new Node(left.freq + right.freq);
            merged.left = left;
            merged.right = right;
            pq.add(merged);
        }

        printCodes(pq.poll(), "");
    }

    private static void printCodes(Node root, String code) {
        if (root.left == null && root.right == null) {
            System.out.println(root.freq + ": " + code);
            return;
        }
        printCodes(root.left, code + "0");
        printCodes(root.right, code + "1");
    }
}

贪心算法的总结

贪心算法通过在每一步选择中都采取局部最优的选择,希望最终得到全局最优解。它通常用于解决一些优化问题,如活动选择问题、背包问题和哈夫曼编码等。虽然贪心算法不总能得到全局最优解,但在某些特定问题上,它能以简单和高效的方式得到全局最优解。理解贪心算法的基本思想和应用场景,有助于在实际问题中选择合适的算法解决方案。

相关推荐
纽扣66712 分钟前
【算法进阶之路】链表进阶:删除、合并、回文与排序全解析
数据结构·算法·链表
消失的旧时光-194330 分钟前
统一并发模型:线程、Reactor、协程本质是一件事(从线程到协程 · 第6篇·终章)
java·python·算法
智者知已应修善业40 分钟前
【51单片机不用数组动态数码管显示字符和LED流水灯】2023-10-3
c++·经验分享·笔记·算法·51单片机
AI进化营-智能译站1 小时前
ROS2 C++开发系列16-智能指针管理传感器句柄|告别ROS2节点内存泄漏与野指针
java·c++·算法·ai
CS创新实验室2 小时前
从盘边到芯端——硬盘接口七十年变迁史
算法·磁盘调度
xvhao20132 小时前
单源、多源最短路
数据结构·c++·算法·深度优先·动态规划·图论·图搜索算法
MATLAB代码顾问3 小时前
多种群协同进化算法(MPCE)求解大规模作业车间调度问题——附MATLAB代码
开发语言·算法·matlab
FQNmxDG4S3 小时前
JVM内存模型详解:堆、栈、方法区与垃圾回收
java·jvm·算法
We་ct3 小时前
LeetCode 72. 编辑距离:动态规划经典题解
前端·算法·leetcode·typescript·动态规划
AI科技星3 小时前
精细结构常数α作为SI 7大基本量纲统一耦合常数的量子几何涌现理论
算法·机器学习·数学建模·数据挖掘·量子计算