四十三、贪心——Huffman树、排序不等式

news/2024/11/27 5:34:56/

算法主要内容

  • 一、Huffman树
    • 1、题目内容——合并果子
    • 2、算法思路
      • (1)“合并果子”中的Huffman树
      • (2)算法步骤
      • (3)状态转移
    • 3、题解
  • 二、排序不等式
    • 1、题目内容——排队打水
    • 2、算法思路
      • (1)分析
      • (2)思路
      • (3)证明
    • 3、题解

一、Huffman树

  • 哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树,且为完全二叉树。
    • 所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。
    • 树的带权路径长度记为WPL=(W1L1+W2L2+W3L3+…+WnLn),N个权值Wi(i=1,2,…n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,…n)。
    • 可以证明哈夫曼树的WPL带权路径长度是最小的
  • 贪心思想:
    • 选最小的两堆进行合并

1、题目内容——合并果子

在这里插入图片描述

2、算法思路

(1)“合并果子”中的Huffman树

  • 叶子结点为我们要进行合并的节点
  • 合并代价为下方两个“代价总和”相加
  • 从下向上开始合并
    在这里插入图片描述
  • 总和:(a + b)+ (c + d) +(a + b + c + d ) + e + f + a +b + c + d + e + f
  • 优化:直接计算当前根节点到根节点距离
    • 3a(到根节点的距离) + 3b + 3c + 3d + 2e + 2f

(2)算法步骤

  • 方法: 每次选出最小的两堆进行合并,寻找局部最优解的过程
    • 数最小的两个点,在树中一定是深度最深的,可以互为兄弟(不一定非得是兄弟节点)
    • 数最小,但并未在最深的一层,则需要交换,这样将使整体权值变小(2f + 3b + -(3f + 2b) = b - f > 0)

(3)状态转移

在这里插入图片描述

3、题解

import java.util.*;
import java.io.*;public class Main{public static void main(String[] args) throws IOException {BufferedReader in = new BufferedReader(new InputStreamReader(System.in));Queue<Integer> heap = new PriorityQueue<>();String str1 = in.readLine();int n = Integer.parseInt(str1);String[] str2 = in.readLine().split(" ");for(int i = 0; i < n; i++){int x = Integer.parseInt(str2[i]);heap.add(x);}int res = 0;while(heap.size() > 1){int a = heap.poll();        // 选最小的两个点int b = heap.poll();res += a + b;               // 合并代价更新heap.add(a + b);            // a + b变成了新的节点}System.out.println(res);}
}

二、排序不等式

  • 排队问题 + 排队代价,如何让总体代价最小
  • 贪心思想:
    • 让代价越大的排序越靠后

1、题目内容——排队打水

在这里插入图片描述

2、算法思路

(1)分析

在这里插入图片描述

(2)思路

  • 按照从小到大的顺序排队,总时间最小

(3)证明

在这里插入图片描述

3、题解

import java.util.*;
import java.io.*;public class Main{static int N = 100010;static int[] time = new int[N];public static void main(String[] args) throws IOException {BufferedReader in = new BufferedReader(new InputStreamReader(System.in));String str1 = in. readLine();int n = Integer.parseInt(str1);String[] str2 = in.readLine().split(" ");for(int i = 0; i < n; i++){time[i] = Integer.parseInt(str2[i]);}Arrays.sort(time, 0 , n);long res = 0;for(int i = 0; i < n; i++){res += time[i]*(n - i - 1);}System.out.println(res);}
}

http://www.ppmy.cn/news/759612.html

相关文章

【Bootstrap 学习笔记】字体图标_下拉菜单_按钮组_警告框_导航_导航条

字体图标 Bootstrap 使用的字体图标是来自 Glyphicions Halflings 提供的。在使用的时候&#xff0c;需要遵守以下几点规则&#xff1a; 图标使用的 class 不能与其他组件的 class 混合使用。换言之&#xff0c;图标的 class 必须被定义在 span 元素上。图标使用的 class 具有…

迁移与备份

容器保存为镜像 我们可以通过以下命令将容器保存为镜像 docker commit mynginx mynginx_i 镜像备份 我们可以通过以下命令将镜像保存为tar 文件 docker save -o mynginx.tar mynginx_i 镜像恢复与迁移 首先我们先删除掉 mynginx_img 镜像 然后执行此命令进行恢复 docker …

Mysql 备份表

CREATE TABLE new_table_name AS SELECT * FROM old_table_name ;

mysql备份表

mysql 备份一个表1、将表备份到物理机mysqldump -h 域名 -P 端口 -u用户 -p密码 库名 表名 > /路径/表名.{$date}.bak 2、将表备份在库里面&#xff08;create复制表结构、insert复制表内容&#xff09;create table one_bak like one; 复制表结构 insert into one_bak …

MySQL数据表的备份

备份数据表 可以先创建一个新表用作备份表&#xff0c;结构和旧表相同 create new_table like old_table; 然后把旧表数据插入新表 insert into new_table select * from old_table

将三星手机备忘录vnt格式文件转为txt格式备份

最近想把手机上的备忘录导出到电脑上备份&#xff0c;结果发现导出来的并不是txt格式&#xff0c;而是三星自己的vnt格式。于是自己用java写了几行代码把它转为txt格式用于备份。留着以后备份的时候用。 import java.io.BufferedReader; import java.io.File; import java.io.F…

备份概述

什么是备份&#xff1f; 备份指的是将文件系统或者数据库中的数据进行复制&#xff0c;一旦发生错误或者灾难时&#xff0c;能及时方便地恢复系统的有效数据和正常运作。 备份的方式有哪些&#xff1f; 全部备份&#xff08;也称完整备份&#xff09;&#xff1a;指把硬盘或数…

备份与恢复(完全备份、增量备份、差异备份)

文章目录 前言1. Linux系统需要备份的数据1.1 安装服务的数据1.2 MySQL需要备份的数据 2. 备份策略3. 总结 前言 什么叫做备份&#xff1a; 把数据拷贝出来复制到其他位置&#xff0c;如果原始数据崩溃了&#xff0c;丢失了&#xff0c;或者出现别的问题。可以把重要数据恢复过…