贪心算法---java---黑马

贪心算法

1)Greedy algorithm

称之为贪心算法或者贪婪算法,核心思想是

  1. 将寻找最优解的问题分为若干个步骤
  2. 每一步骤都采用贪心原则,选取当前最优解
  3. 因为未考虑所有可能,局部最优的堆叠不一定得到最终解最优

贪心算法例子

Dijkstra

while (!list.isEmpty()) {// 选取当前【距离最小】的顶点Vretex curr = chooseMinDistVertex(list);// 更新当前顶点到相邻顶点距离updateNeighboursDish(curr);// list集合中移除当前顶点list.remove(curr);// 标记当前顶点已被访问curr.visited = true;
}
  • 未能找到最短路径:存在负边 情况,得不到正确解;
  • 贪心原则会认为本次已找到该顶点的最短路径,使得该顶点赋为已访问
  • 与之对比,Bellman-Ford算法并未考虑局部距离最小顶点,而是每次处理所有边 ,不会出错,当然效率不如Dijkstra算法;

prim

while (!list.isEmpty()) {// 选取当前【距离最小】的顶点Vretex curr = chooseMinDistVertex(list);// 更新当前顶点到相邻顶点距离updateNeighboursDish(curr);// list集合中移除当前顶点list.remove(curr);// 标记当前顶点已被访问curr.visited = true;
}

prim与Dijkstra的区别在于,根据距离选取最小顶点不同,Dijkstra算法是一个累加距离,而prim算法中距离是跟相邻顶点间的距离

KrusKal

List<String> list = new ArrayList<>();
DisjoinSet set = new DisjoinSet(size);
while (list.size() < size - 1) {// 选取当前【距离最短】的边Edge poll = queue.poll();int i = set.find(poll.start);int j = set.find(poll.end);// 判断两个集合是否相交if (i != j) {// 未相交list.add(poll);set.union(i, j);	// 相交操作}}

其他贪心算法例子

  • 选择排序、堆排序
  • 拓扑排序
  • 并查集和中的union by size 和union by height
  • 哈夫曼编码
  • 钱币找零
  • 任务编排
  • 近似算法

零钱兑换ⅡLeetcode518

递归实现

public class Leetcode518 {public int change(int[] coins, int amount) {return coinChange(coins, 0, amount, new LinkedList<>(), true);}public int coinChange(int[] coins, int index, int amount, LinkedList<Integer> stack, boolean first) {if (!first) {stack.push(coins[i]);}int sum = 0;if (amount == 0) {System.out.printlin(stack);sum = 1;} else if (amount < 0) {System.out.println(stack)sum = 0;} else {for(int i = index; i < coins.length; i++) {sum += coinChange(coins, i, amount - coins[i], stack, false);}}if (!stack.isEmpty()) {stack.pop();}return sum;}
}

零钱兑换Leetcode322

递归实现

public class Leetcode322 {static int min = -1;public int change(int[] coins, int amount) {coinChange(coins, 0, amount, new AtomicInteger(-1), new LinkedList<Integer>(), true);return min;}public void coinChange(int[] coins, int index, int amount, AtomicInteger count, LinkedList<Integer> stack, boolean first) {if (!first) {stack.push(coins[i]);}count.incrementAndGet();	// count++;int sum = 0;if (amount == 0) {System.out.println(stack);if (min == -1) {min = min.get();} else {min = Math.min(min, count.get());}} else {for(int i = index; i < coins.length; i++) {sum += coinChange(coins, i, amount - coins[i], count, stack, false);}}count.decrementAndGet();	// count--;	if (!stack.isEmpty()) {stack.pop();}return sum;}public static void main(String[] args) {int[] coins = {5, 2, 1};Leetcode322 leetcode = new Leetcode322();System.out.printlin(leetcode.coinChange(coins, 5));}
}

贪心实现

public class Leetcode322{public int coinChange(int[] coins, int amount) {// 前提是coins是降序排序int reminder = amount;int count;for(int coin : coins) {while (reminder > coin) {reminder -= coin;count++;}if (reminder == coin) {reminder -= coin;count++;break;}}if (reminder > 0) {return -1;} else {return count;}}}

但是这个代码放到Leetcode上跑,有些测试用例是不能通过。

动态规划实现

使用动态规划求解,如下面代码

public class Leetcode322{public int coinChange(int[] coins, int amount) {int[] dp = new int[amount + 1];Arrays.fill(dp, amount + 1);dp[0] = 0;for(int coin : coins) {for(int j = coin; j < amount + 1; j++) {dp[j] = Math.min(dp[j], dp[j - coin] + 1);}}int r = dp[amount];return r > amount ? -1 : r;}}

哈夫曼编码

Huffman树构建过程

  1. 统计出现频次字符,放入优先级队列
  2. 每次出对两个频次最低元素(小顶堆),
  3. 当队列中只有一个元素时,构建Huffman树完成
public class Huffman{static class Node{Character ch;int freq;Node left;Node right;String code;public Node(Character ch) {this.ch = ch;}public Node(int freq, Node left, Node right) {this.freq = freq;this.left = left;this.right = right;}int getFreq() {return freq;}boolean isLeaf() {return node.left == null;}@Overridepublic void toString() {return "Node{" +"ch=" + ch + ", freq=" + freq +"}";}}String str;Node root;HashMap<Character, Node> map = new HashMap<>();public Huffman(String str) {this.str = str;char[] chars = str.toCharArray();// 1.统计频次for(char ch : chars) {if (!map.containsKey(ch)) {map.put(ch, new Node(ch));} else {Node node = map.get(ch);node.freq++;}//方法引用// Node node = map.computeIfAbsent(ch, Node :: new);// node.frea++;}for(Node node : map.values()) {System.out.println(node.toString());}2.构造树PriorityQueue<Node> queue = new PriorityQueue<>(Comparator.ComparingInt(Node::getFreq));queue.offerAll(map.values());while (queue.size() >= 2) {Node x = queue.poll();Node y = queue.poll();int f = x.freq + y.freq;queue.offer(new Node(f, x, y));}root = queue.poll();System.out.println(root);// 功能3 计算每个字符编码		//功能4 字符串编码后占几个bitint sum = dfs(root, new StringBuilder());		// 得到字符串编码后占的bitfor(Node node : map.values()) {System.out.printlin(node);}System.out.println(sum);}public int dfs(Node node, StringBuilder sb) {int sum = 0;if (node.isLeaf()) {//编码node.node = sb.toString();sum = sb.length() * node.freq;// System.out.println(sb.toString());   } else {sum += dfs(node.left, sb.append("0"));sum += dfs(node.right, sb.append("1"));}if (sb.length() > 0) {sb.deleteCharAt(sb.length() - 1);}return sum;}public String encode() {char[] chars = str.toCharArray();StringBuilder sb = new StringBuilder();for(char ch : chars) {sb.append(map.get(ch).code);}return sb.toString();}public String decode(String str) {int i = 0;char[] chars = str.toCharArray();StringBuilder sb = new StringBuilder();Node node = root;while (i < chars.length) {if (!node.isLeaf()) {if (chars[i] == '0') {node = node.left;} else if (chars[i] == '1'){node = node.right;}i++;} if (node.isLeaf()) {sb.append(node.ch);node = root;}}return sb.toString();}
}

活动选择问题

要在一个会议室举办n个活动

  • 每个活动有它们各自的起始和结束时间
  • 找出时间上不冲突的活动组合,能够最充分利用会议室(举办的活动次数最多)
public class ActivitySelectionProblem{static class Activity{int index;int start;int end;public Activity(int index, int start, int end) {this.index = index;this.start = start;this.end = end;}public int getEnd() {return end;}@Overridepublic void tostring() {return "Activity(" + index + ")";}}public static void main(String[] args) {Activity[] activity = new Activity[]{new Activity(0, 1, 3),new Activity(1, 2, 4),new Activity(2, 3, 5)}	Arrays.sort(activity, Comparator.comparingInt(Activity::getEnd))System.out.println(activity);// select(activity, activity.length);}public void select(Activity[] activity, int n) {List<int[]> res = new ArrayList<>();res.add(activity[0]);Activity pre = res;for(int i = 1; i < n; i++) {Activity curr = activity[i];if (curr.start >= pre.end) {res.add(curr);pre =  curr;}}for(Activity a : res) {System.out.println(a);}}
}

Leetcode435

无重叠区间

public class Leetcode435{public int eraseOverlapIntervals(int[][] intervals) {// 根据数组中的第二个元素先升序排序Arrays.sort(intervals, (a, b) -> a[1] - b[1]);List<int[]> res = new ArrayList<>();res.add(intervals[0]);int[] pre = res.get(0);int count = 0;	// 减少个数for(int i = 1; i < intervals.length; i++) {int[] curr = intervals[i];if (curr[0] < pre[1]) {		// 当前的初始值小于前一个的结束值,有冲突count++;} else {	// 只要当前的初始值大于等于前一个的结束值,则不冲突res.add(curr);pre = curr;}}return count;}
}

分数背包问题

  1. n个液体物品,有重量和价格属性
  2. 现取走10L物品
  3. 每次可以不拿,全拿,拿一部分,问最高价值是多少
    在这里插入图片描述
public class FractionalKnapsackProblem{static class Item{int index;int weight;int value;public Item(int index, int weight, int value) {this.index = index;this.weight = weight;this.value = value;}public int perValue() {return value / weight;}@Overridepublic void toString() {return "Item(" + index + ")";}}public static void main(String[] args) {Item[] items = new Item[]{new Item(0, 4, 24),new Item(1, 8, 160),new Item(2, 2, 4000),new Item(3, 6, 108),new Item(4, 1, 4000),}select(items, 10);}public int select(Item[] items, int n) {Arrays.sort(items, Comparator.comparingInt(Item::preValue).reverse());int sum = 0;for(int i = 0; i < items.length; i++) {Item curr = items[i];if (n >= curr.weight) {n -= curr.weight;sum += curr.value;} else {sum += curr.perValue() * n;break;}}return sum;}
}

0-1背包问题

在这里插入图片描述

  1. n个物体都是固体,有重量和价值
  2. 现取走不超过10克物品
  3. 每次可以不拿或者全拿,问最高价值是多少
public class FractionalKnapsackProblem{static class Item{int index;int weight;int value;public Item(int index, int weight, int value) {this.index = index;this.weight = weight;this.value = value;}public int perValue() {return value / weight;}@Overridepublic void toString() {return "Item(" + index + ")";}}public static void main(String[] args) {Item[] items = new Item[]{new Item(0, 1, 1000000),new Item(1, 4, 1600),new Item(2, 8, 2400),new Item(3, 5, 30),}select(items, 10);}public int select(Item[] items, int n) {Arrays.sort(items, Comparator.comparingInt(Item::preValue).reverse());int sum = 0;for(int i = 0; i < items.length; i++) {Item curr = items[i];if (n >= curr.weight) {n -= curr.weight;sum += curr.value;}}return sum;}
}

得到的结果,最大价值结果是:1001630 ,实际上选择钻石红宝石 得到的价值结果 1002400

贪心算法局限性

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/58938.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Docker Compose搭建多服务应用

使用Docker Compose搭建多服务应用 Docker Compose简介 安装Docker Compose 在Linux上安装Docker Compose 在macOS上安装Docker Compose 在Windows上安装Docker Compose 创建项目结构 Flask应用 安装依赖 Dockerfile 配置Docker Compose 构建和运行应用 访问应用 高级配置 环…

【教程】Git 标准工作流

前言 Git 是日常开发中常用的版本控制工具&#xff0c;配合代码托管仓库&#xff08;如&#xff0c;Github&#xff0c;GitLab&#xff0c;Gitee 等&#xff09;用来实现多人多版本的协作开发。 但是 Git 的命令纷繁复杂&#xff0c;多如累卵&#xff0c;不可能也不需要全部搞…

Vue 3 Vite 项目打包优化:自动删除指定文件的方法

程序员必备宝典https://tmxkj.top/#/ 在 Vue 3 项目中&#xff0c;如果你需要在打包之前删除指定的文件&#xff0c;可以使用 Node.js 的 fs 模块来实现。这可以通过在 vue.config.js 文件中配置一个自定义的 Webpack 插件来完成。 1.安装必要的依赖&#xff08;如果还没…

前端通过nginx部署一个本地服务的方法

前端通过nginx部署一个本地服务的方法&#xff1a; 1.下载ngnix nginx 下载完成后解压缩后运行nginx.exe文件 2.打包你的前端项目文件 yarn build 把生成的dist文件复制出来&#xff0c;替换到nginx的html文件下 3.配置conf目录的nginx.conf文件 主要配置server监听 ser…

【网络面试篇】TCP与UDP类

目录 一、综述 1. TCP与UDP的概念 2. 特点 3. 区别 4. 对应的使用场景 二、补充 1. 基础概念 &#xff08;1&#xff09;面向连接 &#xff08;2&#xff09;可靠的 &#xff08;3&#xff09;字节流 2. 相关问题 &#xff08;1&#xff09;TCP 和 UDP 可以同时绑定…

【触想智能】工业平板电脑在智能教育设备上的应用优势分析

随着科技的快速发展&#xff0c;智能教育设备成为现代教育领域的新宠。其中&#xff0c;工业平板电脑作为一种重要的智能教育设备&#xff0c;正逐渐在教育领域得到广泛应用。 工业平板电脑在智能教育设备上的应用具有以下几个优势。 1、工业平板电脑具备便携性。相比传统的教学…

java项目之协力服装厂服装生产管理系统的设计与实现(springboot)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的协力服装厂服装生产管理系统的设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; …

C语言之写一个修改数组内容的函数

问题代码: 函数ltrim是为了消除buf字符数组中左边空格&#xff0c; memmove函数介绍 如果对c语言指针运用非常熟练的人,结合函数功能就会发现这个代码非常的傻逼&#xff0c;你会发现为什么需要返回&#xff0c;buf不用接收返回值&#xff0c;执行这个函数后buf中的内容就已经…

基于SSM+VUE宠物医院后台管理系统JAVA|VUE|Springboot计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…

Cisco Packet Tracer 8.0 路由器静态路由配置

文章目录 静态路由简介一、定义与特点二、配置与命令三、优点与缺点四、应用场景 一&#xff0c;搭建拓扑图二&#xff0c;配置pc IP地址三&#xff0c;pc0 ping pc1 timeout四&#xff0c;配置路由器Router0五&#xff0c;配置路由器Router1六&#xff0c;测试 静态路由简介 …

MPSK(BPSK/QPSK/8PSK)调制解调的Matlab仿真全套

一、概述 MPSK(BPSK、QPSK、8PSK)等是常用的相位调制方式,本文对数据获取、比特流组织、基带调制、上变频发送、添加噪声、接收下变频、基带解调、数据还原等过程进行仿真。 模块化、通用化设计,将函数分为(1)数据读取转比特流;(2)基带调制【参数控制调制类型】;(…

Python-创建并调用自定义文件中的模块/函数

背景&#xff1a;在Python编程中&#xff0c;我们常常需要创建自己的专属文件&#xff0c;以便帮助我们更高效&#xff0c;快捷地完成任务。那么在Python中我们怎么创建并调用自己文件中的模块/函数呢? 在Python中调用自定义文件&#xff0c;通常是指调用自己编写的Python模块…

基于STM32的智能窗帘控制系统设计

引言 本项目将基于STM32微控制器设计一个智能窗帘控制系统&#xff0c;用户可以通过按钮或遥控器控制窗帘的开关&#xff0c;并且系统能够根据光照强度自动调节窗帘的开合状态。该项目展示了STM32微控制器在家居自动化中的应用&#xff0c;以及与光照传感器、直流电机和红外接…

鸿蒙ArkTS中的image组件

开发文档很详尽&#xff0c;就在DevEco中的API参考&#xff0c;可以随时调出来进行学习。 在鸿蒙官网也有非常详尽的资料&#xff0c;地址&#xff1a;开发说明-API参考概述 - 华为HarmonyOS开发者 (huawei.com) 这里&#xff0c;就学习image组件的一般用法以及使用SVG图标和字…

opencv 图像预处理

图像预处理 ​ 在计算机视觉和图像处理领域&#xff0c;图像预处理是一个重要的步骤&#xff0c;它能够提高后续处理&#xff08;如特征提取、目标检测等&#xff09;的准确性和效率。OpenCV 提供了许多图像预处理的函数和方法&#xff0c;以下是一些常见的图像预处理操作&…

kafka里的consumer 是推还是拉?

大家好&#xff0c;我是锋哥。今天分享关于【kafka里的consumer 是推还是拉&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; kafka里的consumer 是推还是拉&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Kafka中&#xff0c;消费者&…

第7章 利用CSS和多媒体美化页面作业

2.用表格布局页面&#xff0c;利用CSS技术&#xff0c;及添加多媒体&#xff0c;制作并美化“心灵之音”页面。 浏览效果如下&#xff1a; 实例代码如下&#xff1a; <!DOCTYPE html> <html><head><meta charset"utf-8"><title>心灵…

Cisco Packet Tracer 8.0 路由器的基本配置和Telnet设置

文章目录 构建拓扑图配置IP地址配置路由器命令说明测试效果 构建拓扑图 1&#xff0c;添加2811路由器。 2&#xff0c;添加pc0。 3&#xff0c;使用交叉线连接路由器和pc&#xff08;注意线路端口&#xff09;。 4&#xff0c;使用配置线连接路由器和pc&#xff08;注意线路…

Python实现全国岗位招聘信息可视化分析(源码+论文+部署讲解)

项目源码&数据源获取 利用Python实现全国岗位招聘信息可视化分析 项目背景&#xff1a; 1.为企业招聘决策提供科学的依据和参考&#xff0c;可以帮助人力资源部门、招聘机构和求职者了解当前的就业形势、行业趋势和人才需求&#xff0c;从而做出更明智的招聘和求职决策。…

(九)JavaWeb后端开发3——Servlet

目录 1.Servlet由来 2.Servlet快速入门 3.Servlet执行原理 4.Servlet生命周期 1.Servlet由来 在JaveEE API文档中对Servlet的描述是&#xff1a;可以运行在服务器端的微小程序&#xff0c;但是实际上&#xff0c;Servlet就是一个接口&#xff0c;定义了Java类被浏览器访问…