极客时间:数据结构与算法之美【文章笔记 实践 总结】

原文链接:https://time.geekbang.org/column/intro/100017301

  • 27 | 递归树:如何借助树来求解递归算法的时间复杂度?
    • 如何借助树来分析归并排序算法的时间复杂度?
    • 如何借助树来分析快速排序算法的时间复杂度?
    • 如何借助递归树来分析斐波那契数列的时间复杂度?
    • 如何借助递归树来分析全排列的时间复杂度?
    • 1 个细胞的生命周期是 3 小时,1 小时分裂一次。求 n 小时后,容器内有多少细胞?如何分析递归时间时间复杂度?
  • 28 | 堆和堆排序:为什么说堆排序没有快速排序快?
    • 如何理解 "堆"?
    • 如何实现一个堆?
      • 如何存储一个堆?
      • 堆支持哪些操作?
        • 插入元素
        • 删除堆顶元素
    • 如何基于堆实现排序?
      • 建堆
      • 排序
    • 解答开篇
    • 内容小结
    • 课后思考
  • 29 | 堆的应用:如何快速获取到Top 10最热门的搜索关键词?

27 | 递归树:如何借助树来求解递归算法的时间复杂度?

如何借助树来分析归并排序算法的时间复杂度?

归并排序递归树
每次分解一分为二,代价很低,时间上消耗记作O(1)。
每一层合并消耗时间相同,和数据规模相关,记作 O(n)。
归并排序递归树是一颗满二叉树,高度为 log2n。
归并排序时间复杂度:O(n logn)。

如何借助树来分析快速排序算法的时间复杂度?

平均情况:1 : k
k = 9 时。

快速排序递归树

每一层遍历 n 个元素。
快速排序结束条件:叶子节点 1 个元素。
根节点 n 个元素到叶子节点 1 个元素最短路径每一层乘 1 /10,最长路径每一层乘 9 / 10。
根节点到叶子节点最短路径:log10n,最长路径 log(10 / 9 ) n。
遍历个数在 n * log10 到 n * log(10 / 9 ) n 之间,快速排序时间复杂度为:O(n logn)。

k 的值不随 n 改变,对最终时间复杂度无影响。

如何借助递归树来分析斐波那契数列的时间复杂度?

斐波那契数列的递归树

f(n) 分解为 f(n - 1) 和 f(n - 2),每次数据规模 -1 或 -2,叶子节点数据规模是 1 或者 2。
根节点到叶子节点最长为 n ,最短为 n / 2。
合并的操作只需要一次加法运算,耗时记作 O(1)。
每一层消耗时间为 2^ (k - 1) ,路径长度为 n 总和为 2^n - 1。
在这里插入图片描述
路径长度为 n 总和为 2^(n / 2) - 1。
在这里插入图片描述
时间复杂度为指数级别。

如何借助递归树来分析全排列的时间复杂度?

最后一位有 n 种情况,求解 n 个 “n - 1数据的排列” 的子问题。

递推公式:

假设数组中存储的是123...n。f(1,2,...n) = {最后一位是1, f(n-1)} + {最后一位是2, f(n-1)} +...+{最后一位是n, f(n-1)}

全排列

第一层有 n 此交换,第二层有 n (n - 1) 次交换,第三层有 n(n - 1)(n - 2) 此交换,最后一层有 n(n - 1)(n - 2) *…21 次交换。

总交换次数:

n + n*(n-1) + n*(n-1)*(n-2) +... + n*(n-1)*(n-2)*...*2*1
n*(n-1)*(n-2)*...*2*1 为 n!

总和小于 n * n!,全排列递归时间复杂度大于O(n!),小于O(n * n!)。时间复杂度非常高。

1 个细胞的生命周期是 3 小时,1 小时分裂一次。求 n 小时后,容器内有多少细胞?如何分析递归时间时间复杂度?

需要重新系统完整的分析。

28 | 堆和堆排序:为什么说堆排序没有快速排序快?

特殊的树:堆(Heap)。
堆排序:原地排序,时间复杂度为O(n logn)。

如何理解 “堆”?

堆满足的条件是什么?(2个)

  • 堆是一个完全二叉树。(除了最后一层,其他层节点个数都是满的,最后一层的节点都靠左排列。)
  • 堆中每个节点的值都大于等于[大顶堆](或小于等于[小顶堆])其左右子节点的值。

定义堆

1 和 2是大顶堆,3是小顶堆,4不是堆。

如何实现一个堆?

如何存储一个堆?

完全二叉树用数组存储。

完全二叉树

下标为 i 的左子节点下标为 i * 2,右子节点下标为 i * 2 + 1,父节点为下标 i / 2 的节点。

堆支持哪些操作?

插入元素

往堆中插入一个元素,满足堆的特性,通过堆化实现。堆

从下往上堆化:顺着节点所在的路径,向上或者向下,对比,然后交换。
堆化的详细过程
堆化的代码实现过程:

public class Heap {private int[] a; // 数组,从下标1开始存储数据private int n;  // 堆可以存储的最大数据个数private int count; // 堆中已经存储的数据个数public Heap(int capacity) {a = new int[capacity + 1];n = capacity;count = 0;}public void insert(int data) {if (count >= n) return; // 堆满了++count;a[count] = data;int i = count;while (i/2 > 0 && a[i] > a[i/2]) { // 自下往上堆化swap(a, i, i/2); // swap()函数作用:交换下标为i和i/2的两个元素i = i/2;}}}
删除堆顶元素

把最后一个节点放在堆顶,父子节点对比,不满足父子节点大小关系的,互换两个节点。重复该过程,知道父子节点之间满足大小关系为止。

移除的是数组中最后一个元素,堆化的过程都是数据交换操作,不会出现数组空洞。
删除堆顶元素

代码演示:

public void removeMax() {if (count == 0) return -1; // 堆中没有数据a[1] = a[count];--count;heapify(a, count, 1);
}private void heapify(int[] a, int n, int i) { // 自上往下堆化while (true) {int maxPos = i;if (i*2 <= n && a[i] < a[i*2]) maxPos = i*2;if (i*2+1 <= n && a[maxPos] < a[i*2+1]) maxPos = i*2+1;if (maxPos == i) break;swap(a, i, maxPos);i = maxPos;}
}

n 个节点的完全二叉树,树高度不会超过 log2n。
堆化时间复杂度和树高度成正比,为O(log n)。
插入元素和删除堆顶元素主要逻辑是堆化,时间复杂度为O(log n)。

如何基于堆实现排序?

时间复杂度稳定为 O(n logn),原地排序算法。

建堆

第一种:在堆中插入一个元素的思路。从前往后处理数组,从下往上堆化。

第二种:从后往前处理数组,每个数据都从上往下堆化。
叶子节点往下堆化只能自己和自己比较,所以从最后一个非叶子节点开始堆化:
从上往下堆化
从上往下堆化

private static void buildHeap(int[] a, int n) {for (int i = n/2; i >= 1; --i) {heapify(a, n, i);}
}private static void heapify(int[] a, int n, int i) {while (true) {int maxPos = i;if (i*2 <= n && a[i] < a[i*2]) maxPos = i*2;if (i*2+1 <= n && a[maxPos] < a[i*2+1]) maxPos = i*2+1;if (maxPos == i) break;swap(a, i, maxPos);i = maxPos;}
}

建堆的时间复杂度:
叶子节点不需要堆化,需要堆化的节点从倒数第二层开始。每个节点的堆化过程,比较和交换的节点个数,根节点的高度 k 成正比。

每一层节点个数和对应的高度换出来如下:
节点个数及高度

将每个节点的高度求和,得出的就是建堆的时间复杂度。

每个非叶子节点高度求和:
每个非叶子节点高度求和

把公式左右都乘以 2,就得到另一个公式 S2。我们将 S2 错位对齐,并且用 S2 减去 S1,可以得到 S

结果

通过等比数列求和公式:
等比数列求和

h = log2你,带入公式,S = O(n),建堆时间复杂度为O(n)。

排序

数组中第一个元素,堆顶最大元素和最后一个元素交换,最大元素放到下标为 n 的位置。
将 n - 1 个元素重新构建成堆,再取堆顶元素放到 n - 1 ,一直重复,最后堆中只有下标为 1 的一个元素,排序工作就完成了。

堆排序

代码演示:

// n表示数据的个数,数组a中的数据从下标1到n的位置。
public static void sort(int[] a, int n) {buildHeap(a, n);int k = n;while (k > 1) {swap(a, 1, k);--k;heapify(a, k, 1);}
}

原地排序。
建堆时间复杂度为 O(n),排序过程时间复杂度为O(n logn),堆整体的时间复杂度为 O(n logn)。
不稳定排序。

解答开篇

堆排序数据访问方式没有快速排序友好。
快速排序,数据顺序访问,可以有效利用CPU缓存。
堆排序,数据跳着访问。

堆顶节点堆化,会依次访问数组下标1,2,4,8。
堆化

同样的数据,排序过程中,堆排序算法的数据交换次数多于快速排序。
快速排序数据交换次数不会比逆序度多。
堆排序第一步是建堆,建堆会打乱数据原有的先后顺序,导致原数据有序度降低。

堆化后有序度降低

内容小结

堆是一种完全二叉树。
大顶堆和小顶堆。

插入一个数据:新插入元素放到数组最后,从下往上堆化。时间复杂度:O(logn)
删除堆顶元素:将数组中最后一个元素放到堆顶,从上往下堆化。时间复杂度:O(logn)

堆排序:
建堆:将下标从 n / 2 到 1 的节点,依次从上到下堆化操作,将数组中的数据组织成堆这种数据结构。
排序:迭代的将堆顶元素放在堆末尾,将堆大小减一,然后再堆化。重复这个过程,直到堆中只剩下一个元素,整个数组中数据有序。

课后思考

对于完全二叉树来说,下标从 n / 2​+1 到 n 的都是叶子节点,这个结论是怎么推导出来的呢?

关于堆,你还能想到它的其他应用吗?

29 | 堆的应用:如何快速获取到Top 10最热门的搜索关键词?

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

看阿里测试工程师如何玩转postman+newman+jenkins接口自动化

【软件测试面试突击班】如何逼自己一周刷完软件测试八股文教程&#xff0c;刷完面试就稳了&#xff0c;你也可以当高薪软件测试工程师&#xff08;自动化测试&#xff09; postman用来做接口测试非常方便&#xff0c;接口较多时&#xff0c;则可以实现接口自动化 一、环境准备…

04-Flask-新版Flask运行方式

新版Flask运行方式 前言老版本运行方式新版本运行方式命令行方式运行pycharm运行 前言 本篇来学习下新版Flask运行方式 老版本运行方式 app.run()&#xff1a;1.0之前版本 # -*- coding: utf-8 -*- # Time : 2023/9/16 # Author : 大海# 导入flask from flask import F…

Python爬虫:获取必应图片的下载链接

文章目录 1. 前言2. 实现思路3. 运行结果 1. 前言 首先&#xff0c;说明一下&#xff0c;本篇博客内容可能涉及到版权问题&#xff0c;为此&#xff0c;小编只说明一下实现思路&#xff0c;至于全部参考代码&#xff0c;小编不粘贴出来。不过&#xff0c;小编会说明详细一些&a…

ArcGIS 10.3软件安装包下载及安装教程!

【软件名称】&#xff1a;ArcGIS 10.3 【安装环境】&#xff1a;Windows 【下载链接 】&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1K5ab7IHMYa23HpmuPkFa1A 提取码&#xff1a;oxbb 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 软件解压码点击原文…

【学习草稿】背包问题

一、01背包问题 图解详细解析 &#xff08;转载&#xff09; https://blog.csdn.net/qq_37767455/article/details/99086678 &#xff1a;Vi表示第 i 个物品的价值&#xff0c;Wi表示第 i 个物品的体积&#xff0c;定义V(i,j)&#xff1a;当前背包容量 j&#xff0c;前 i 个物…

管道的读写特点和管道设置为非阻塞

管道的读写特点&#xff1a; 使用管道时&#xff0c;需要注意&#xff08;默认阻塞I/O操作&#xff09; 1.所有的指向管道写端的文件描述符都关闭了&#xff08;管道写端引用计数为0&#xff09;&#xff0c;有进程从管道的读端读数据&#xff0c;那么管道中剩余的数据被读取以…

Postman应用——接口请求和响应(Get和Post请求)

文章目录 新增Request请求Get请求Post请求 Request请求响应Postman响应界面说明请求响应另存为示例&#xff08;模板&#xff09;Postman显示的响应数据清空请求响应数据保存到本地文件 这里只讲用的比较多的Get和Post请求方式&#xff0c;也可以遵循restful api接口规范&#…

acwing算法基础-chapter01-差分

差分介绍 结论&#xff1a;差分是前缀和的逆运算 举例 一维差分 //一维前缀和 a[i]部分就是一维差分数组 s[i] s[i-1]a[i]; //一维差分 a[i] s[i]-s[i-1];二维差分 //二维前缀和 a[i][j]部分就是一维差分数组 s[i][j] s[i-1][j]s[i][j-1]-s[i-1][j-1]a[i][j]; //二维差分…

时序预测 | MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元时间序列预测

时序预测 | MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元时间序列预测 目录 时序预测 | MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元时间序列预测效果一览基本介绍模型搭建程序设计参考资料 效果一览 基本介绍 MATLAB实现BO-BiGRU贝叶斯优化双向门控循环单元时间序列预测。…

北工大汇编——综合题(1)

题目要求 统计字符数。从键盘输入一行字符&#xff0c;统计字母、空格、数字、其他宇符的个数&#xff0c;并显示。要求&#xff1a;提示输入一行宇符串&#xff1b;键盘输入宇符串&#xff0c;Enter 键结束输入&#xff0c;并换行显示结果。 题目代码 DATAS SEGMENT;此处输…

提前放电避雷针防雷综合应用方案

放电避雷针是一种利用电离空气提前放电的避雷装置&#xff0c;可以有效地保护建筑物、设备和人员免受雷电的危害。放电避雷针有多种类型&#xff0c;根据其放电机理和结构特点&#xff0c;可以分为以下几类&#xff1a; 地凯科技预放电避雷针&#xff1a;这种避雷针利用雷云产…

图神经网络系列之消息传递

文章目录 1.前言2.消息传递机制1.RecGNN2.ConvGNNs3.GAT 1.前言 相比较于神经网络最基本的网络结构全连接层&#xff08;MLP&#xff09;&#xff0c;特征矩阵乘以权重矩阵&#xff0c;图神经网络多了一个邻接矩阵。计算形式很简单&#xff0c;三个矩阵相乘再加上一个非线性变…

C++之类和函数权限访问总结(二百二十七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

数据集笔记:T-drive 北京出租车轨迹数据

数据地址&#xff1a;T-Drive trajectory data sample - Microsoft Research 1 数据描述 此数据集包含了2008年2月2日至2月8日在北京期间10,357辆出租车的GPS轨迹。此数据集中的总点数约为1500万&#xff0c;轨迹的总距离达到了900万公里。图1显示了两个连续点之间的时间间隔和…

数据通信——传输层TCP(超时时间选择)

引言 TCP每一次发送报文段&#xff0c;就会对这个报文段设置一次计时器。如果时间到了却没有收到确认报文&#xff0c;那么就要重传该报文。 这个之前在TCP传输的机制中提到过&#xff0c;这个章节就来研究一下超时时间问题。 关于加权的概念 有必要提及一下加权的概念&#x…

typescrip接口 interface详解,以及ts实现多态

ts 接口 当一个对象类型被多次使用时,一般会使用接口(interface)来描述对象的类型,达到复用的目的 示例如下 当一个对象类型被多次使用时,可以看到,很明显代码有大量的冗余 let personTom: { name: string, age?: number, sayHi(name: string): void } {name: Tom,sayHi(n…

软件的开发步骤,需求分析,开发环境搭建,接口文档 ---苍穹外卖1

目录 项目总览 开发准备 开发步骤 角色分工 软件环境 项目介绍 产品原型 技术选型 开发环境搭建 前端:默认已有 后端 使用Git版本控制 数据库环境搭建 前后端联调 ​登录功能完善 导入接口文档 使用swagger​ 和yapi的区别 常用注解 项目总览 开发准备 开发步骤…

【js】navigator.mediaDevices.getDisplayMedia实现屏幕共享:

文章目录 一、效果图:二、实现思路:三、实现代码: 一、效果图: 二、实现思路: 文档&#xff1a; 【MDN】https://developer.mozilla.org/zh-CN/docs/Web/API/Navigator/mediaDevices web技术分享| WebRTC 实现屏幕共享 面试官&#xff1a;纯前端如何实现录屏并保存视频到本地&a…

企业电子招投标采购系统源码之电子招投标的组成

功能模块&#xff1a; 待办消息&#xff0c;招标公告&#xff0c;中标公告&#xff0c;信息发布 描述&#xff1a; 全过程数字化采购管理&#xff0c;打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力&#xff0c;为外部供…

云计算行业人才缺口巨大,给自己一个超车涨薪的机会!

2023年了&#xff0c;云计算已经不是未来趋势&#xff0c;而是我们正处于的环境&#xff01; 你一定用过云笔记、云盘吧&#xff1f;大家其实都在跟“云”打交道&#xff01;我们如今所处的时代中&#xff0c;云计算无疑是当下最热门的技术。 各大中小企业都在纷纷是将自己的…