算法思想之分治-归并
欢迎拜访:雾里看山-CSDN博客
本篇主题:算法思想之分治-归并
发布时间:2025.4.17
隶属专栏:算法
目录
- 算法介绍
- 核心思想与步骤
- 时空复杂度分析
- C++代码实现
- 关键特性与优化
- 例题
- 排序数组
- 题目链接
- 题目描述
- 算法思路
- 代码实现
- 交易逆序对的总数
- 题目链接
- 题目描述
- 算法思路
- 代码实现
- 升序的版本
- 降序的版本
- 计算右侧小于当前元素的个数
- 题目链接
- 题目描述
- 算法思路
- 代码实现
- 翻转对
- 题目链接
- 题目描述
- 算法思路
- 代码实现
算法介绍
归并排序(Merge Sort)是一种基于分治思想的高效排序算法,其核心思想是通过递归地将数组分解为最小单元,再有序合并子数组完成整体排序。
核心思想与步骤
- 分解(Divide)
将待排序数组递归地分成两个子数组,直到每个子数组仅包含一个元素(天然有序)。 - 解决(Conquer)
递归地对子数组进行排序。 - 合并(Merge)
将两个已排序的子数组合并为一个有序数组。合并时按顺序比较元素,依次放入临时数组,再复制回原数组。
时空复杂度分析
- 最优/平均/最坏时间复杂度:均为
O(n log n)
分解过程产生log n
层递归,每层合并操作时间复杂度为O(n)
。 - 空间复杂度:
O(n)
合并时需要与原始数组等长的临时空间。
C++代码实现
#include <vector>
using namespace std;// 合并两个有序子数组
void merge(vector<int>& arr, int left, int mid, int right) {vector<int> temp(right - left + 1);int i = left, j = mid + 1, k = 0;// 按顺序合并左右子数组while (i <= mid && j <= right) {if (arr[i] <= arr[j]) temp[k++] = arr[i++];else temp[k++] = arr[j++];}// 处理剩余元素while (i <= mid) temp[k++] = arr[i++];while (j <= right) temp[k++] = arr[j++];// 将合并结果复制回原数组for (int p = 0; p < k; p++) {arr[left + p] = temp[p];}
}// 归并排序递归函数
void mergeSort(vector<int>& arr, int left, int right) {if (left >= right) return; // 递归终止条件int mid = left + (right - left) / 2;mergeSort(arr, left, mid); // 递归排序左半部分mergeSort(arr, mid + 1, right);// 递归排序右半部分merge(arr, left, mid, right); // 合并有序子数组
}// 示例调用
int main() {vector<int> arr = {12, 11, 13, 5, 6, 7};mergeSort(arr, 0, arr.size() - 1);// 输出结果:5 6 7 11 12 13return 0;
}
关键特性与优化
- 稳定性
合并时优先保留左侧子数组的相等元素,保证排序稳定。 - 适用场景
外部排序:适合处理磁盘或网络中的大规模数据(需分块加载)。
链表排序:合并过程无需随机访问,天然适配链表结构。 - 优化策略
小数组切换插入排序:当子数组长度较小时(如 ≤ 15),插入排序更高效。
避免频繁内存分配:预分配全局临时数组,减少递归中的内存开销。
例题
排序数组
题目链接
912. 排序数组
题目描述
给你一个整数数组
nums
,请你将该数组升序排列。
你必须在 不使用任何内置函数 的情况下解决问题,时间复杂度为O(nlog(n))
,并且空间复杂度尽可能小。
示例 1:输入:nums = [5,2,3,1]
输出:[1,2,3,5]示例 2:
输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]提示:
1 <= nums.length <= 5 * 104
-5 * 104 <= nums[i] <= 5 * 104
算法思路
归并排序的流程充分的体现了分而治之的思想,大体过程分为两步:
- 分:将数组一分为二两部分,一直分解到数组的长度为 1 ,使整个数组的排序过程被分为左半部分排序 + 右半部分排序;
- 治:将两个较短的有序数组合并成一个长的有序数组,一直合并到最初的长度。
代码实现
class Solution {vector<int> tmp;
public:vector<int> sortArray(vector<int>& nums) {tmp.resize(nums.size());mergeSort(nums, 0, nums.size()-1);return nums;}void mergeSort(vector<int>& nums, int left, int right){if(left >= right)return ;// 1. 选择中间点int mid = left + (right-left)/2;// 2. 把左右区间排序mergeSort(nums, left, mid);mergeSort(nums, mid+1, right);// 3. 把左右区间合并int cur1 = left, cur2 = mid+1, i = left;while(cur1 <= mid && cur2 <= right){tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];}while(cur1 <= mid)tmp[i++] = nums[cur1++];while(cur2 <= right)tmp[i++] = nums[cur2++];// 4. 还原for(int i = left; i <= right; i++)nums[i] = tmp[i];}
};
交易逆序对的总数
题目链接
LCR 170. 交易逆序对的总数
题目描述
在股票交易中,如果前一天的股价高于后一天的股价,则可以认为存在一个交易逆序对。请设计一个程序,输入一段时间内的股票交易记录
record
,返回其中存在的交易逆序对总数。
示例 1:输入:record = [9, 7, 5, 4, 6]
输出:8
解释:交易中的逆序对为 (9, 7), (9, 5), (9, 4), (9, 6), (7, 5), (7, 4), (7, 6), (5, 4)。提示:
0 <= record.length <= 50000
算法思路
用归并排序求逆序数是很经典的方法,主要就是在归并排序的合并过程中统计出逆序对的数量,也就是在合并两个有序序列的过程中,能够快速求出逆序对的数量。
如果我们将数组从中间划分成两个部分,那么我们可以将逆序对产生的方式划分成三组:
- 逆序对中两个元素:全部从左数组中选择
- 逆序对中两个元素:全部从右数组中选择
- 逆序对中两个元素:一个选左数组另一个选右数组
根据排列组合的分类相加原理,三种种情况下产生的逆序对的总和,正好等于总的逆序对数量。
因此,我们可以利用归并排序的过程,先求出左半数组中逆序对的数量,再求出右半数组中逆序对的数量,最后求出一个选择左边,另一个选择右边情况下逆序对的数量,三者相加即可。
代码实现
升序的版本
class Solution {vector<int> tmp;
public:int reversePairs(vector<int>& record) {tmp.resize(record.size());int ret = 0;return mergeSort(record, 0, record.size()-1);}int mergeSort(vector<int> &nums, int left, int right){int ret = 0;if(left >= right)return ret;// 1.选择中间点int mid = left + (right - left)/2;// 2.对左右区间进行排序ret+=mergeSort(nums, left, mid);ret+=mergeSort(nums, mid+1, right);// 3. 统计并合并左右区间int cur1 = left, cur2 = mid+1, i = left;while(cur1 <= mid && cur2 <= right){if(nums[cur1] <= nums[cur2]){tmp[i++] = nums[cur1++];}else{ret+=mid-cur1+1;tmp[i++] = nums[cur2++];}}while(cur1 <= mid)tmp[i++] = nums[cur1++]; while(cur2 <= right)tmp[i++] = nums[cur2++];// 4. 还原for(int i = left; i <= right; i++){nums[i] = tmp[i]; }return ret;}
};
降序的版本
class Solution {vector<int> tmp;
public:int reversePairs(vector<int>& record) {tmp.resize(record.size());int ret = 0;return mergeSort(record, 0, record.size()-1);}int mergeSort(vector<int> &nums, int left, int right){int ret = 0;if(left >= right)return ret;// 1.选择中间点int mid = left + (right - left)/2;// 2.对左右区间进行排序ret+=mergeSort(nums, left, mid);ret+=mergeSort(nums, mid+1, right);// 3. 统计并合并左右区间int cur1 = left, cur2 = mid+1, i = left;while(cur1 <= mid && cur2 <= right){if(nums[cur1] <= nums[cur2]){tmp[i++] = nums[cur2++];}else{ret+=right-cur2+1;tmp[i++] = nums[cur1++];}}while(cur1 <= mid)tmp[i++] = nums[cur1++]; while(cur2 <= right)tmp[i++] = nums[cur2++];// 4. 还原for(int i = left; i <= right; i++){nums[i] = tmp[i]; }return ret;}
};
计算右侧小于当前元素的个数
题目链接
315. 计算右侧小于当前元素的个数
题目描述
给你一个整数数组
nums
,按要求返回一个新数组counts
。数组counts
有该性质:counts[i]
的值是nums[i]
右侧小于nums[i]
的元素的数量。
示例 1:输入:nums = [5,2,6,1]
输出:[2,1,1,0]
解释:
5 的右侧有 2 个更小的元素 (2 和 1)
2 的右侧仅有 1 个更小的元素 (1)
6 的右侧有 1 个更小的元素 (1)
1 的右侧有 0 个更小的元素示例 2:
输入:nums = [-1]
输出:[0]示例 3:
输入:nums = [-1,-1]
输出:[0,0]提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
算法思路
这一道题的解法与 求数组中的逆序对 的解法是类似的,但是这一道题要求的不是求总的个数,而是要返回一个数组,记录每一个元素的右边有多少个元素比自己小。
但是在我们归并排序的过程中,元素的下标是会跟着变化的,因此我们需要一个辅助数组,来将数组元素和对应的下标绑定在一起归并,也就是再归并元素的时候,顺势将下标也转移到对应的位置上。
由于我们要快速统计出某一个元素后面有多少个比它小的,因此我们可以利用求逆序对的第二种方法。
代码实现
class Solution {vector<int> ret;vector<int> index;vector<int> tmp_num;vector<int> tmp_index;
public:vector<int> countSmaller(vector<int>& nums) {int n = nums.size();ret.resize(n);index.resize(n);tmp_num.resize(n);tmp_index.resize(n);for(int i = 0; i < n; i++)index[i] = i;mergeSort(nums, 0, n-1);return ret;}void mergeSort(vector<int>& nums, int left, int right){if(left >= right)return ;// 1. 选择中间点int mid = left + (right-left)/2;// 2. 把左右区间排序mergeSort(nums, left, mid);mergeSort(nums, mid+1, right);// 3. 把左右区间合并int cur1 = left, cur2 = mid+1, i = left;while(cur1 <= mid && cur2 <= right){if(nums[cur1] <= nums[cur2]){tmp_num[i] = nums[cur2];tmp_index[i++] = index[cur2++];}else{ret[index[cur1]] += right-cur2+1;tmp_num[i] = nums[cur1];tmp_index[i++] = index[cur1++];}}while(cur1 <= mid){tmp_num[i] = nums[cur1];tmp_index[i++] = index[cur1++];}while(cur2 <= right){tmp_num[i] = nums[cur2];tmp_index[i++] = index[cur2++];}// 4. 还原for(int i = left; i <= right; i++){nums[i] = tmp_num[i];index[i] = tmp_index[i];}}
};
翻转对
题目链接
493. 翻转对
题目描述
给定一个数组
nums
,如果i < j
且nums[i] > 2*nums[j]
我们就将(i, j)
称作一个重要翻转对。
你需要返回给定数组中的重要翻转对的数量。
示例 1:输入: [1,3,2,3,1]
输出: 2示例 2:
输入: [2,4,3,5,1]
输出: 3注意:
- 给定数组的长度不会超过
50000
。- 输入数组中的所有数字都在
32
位整数的表示范围内。
算法思路
大思路与求逆序对的思路一样,就是利用归并排序的思想,将求整个数组的翻转对的数量,转换成三部分: 左半区间翻转对的数量,右半区间翻转对的数量,一左一右选择时翻转对的数量。 重点就是在合并区间过程中,如何计算出翻转对的数量。
与上个问题不同的是,上一道题我们可以一边合并一遍计算,但是这道题要求的是左边元素大于右边元素的两倍,如果我们直接合并的话,是无法快速计算出翻转对的数量的。
因此我们需要在归并排序之前完成翻转对的统计。
综上所述,我们可以利用归并排序的过程,将求一个数组的翻转对转换成求 左数组的翻转对数量 +右数组中翻转对的数量 + 左右数组合并时翻转对的数量。
代码实现
class Solution {vector<int> tmp;
public:int reversePairs(vector<int>& nums) {tmp.resize(nums.size());return mergeSort(nums, 0, nums.size()-1);}int mergeSort(vector<int>& nums, int left, int right){if(left >= right)return 0;int ret = 0; // 1. 选择中间点int mid = left + (right-left)/2;// 2. 把左右区间排序ret += mergeSort(nums, left, mid);ret += mergeSort(nums, mid+1, right);// 3. 计算两部分之间的翻转对int cur1 = left, cur2 = mid+1, i = left;while(cur1 <= mid && cur2 <= right){if((long long)nums[cur1] > (long long)nums[cur2]*2){ret+=right-cur2+1;cur1++;}elsecur2++;}// 4. 把左右区间合并cur1 = left, cur2 = mid+1, i = left;while(cur1 <= mid && cur2 <= right)//降序{tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur2++] : nums[cur1++];}while(cur1 <= mid)tmp[i++] = nums[cur1++];while(cur2 <= right)tmp[i++] = nums[cur2++];// 5. 还原for(int i = left; i <= right; i++)nums[i] = tmp[i];return ret;}
};
⚠️ 写在最后:以上内容是我在学习以后得一些总结和概括,如有错误或者需要补充的地方欢迎各位大佬评论或者私信我交流!!!
相关文章:
算法思想之分治-归并
欢迎拜访:雾里看山-CSDN博客 本篇主题:算法思想之分治-归并 发布时间:2025.4.17 隶属专栏:算法 目录 算法介绍核心思想与步骤时空复杂度分析C代码实现关键特性与优化 例题排序数组题目链接题目描述算法思路代码实现 交易逆序对的总…...
Vue基础(5)_事件修饰符
事件修饰符 Vue中的事件修饰符: 1、prevent:阻止默认事件(常用)。 2、stop:阻止事件冒泡(常用)。 3、once:事件只触发一次(常用)。 4、capture:使用事件的捕获模式。 5、self:只有event.target是当前操作的…...
网络编程 - 1
目录 为什么需要网络编程? —— 丰富的网络资源 什么是网络编程 网络编程中的基本概念 发送端和接收端 请求和相应 客户端和服务端 常见的客户端服务端模型 Socket 套接字 概念 分类 解释 有连接 / 无连接 可靠传输 / 不可靠传输 面向字节流 / 面向数…...
github | 仓库权限管理 | 开权限
省流版总结: github 给别人开权限:仓库 -> Setting -> Cllaborate -> Add people GitHub中 将公开仓库改为私有:仓库 -> Setting -> Danger Zone(危险区) ->Change repository visibility( 更改仓…...
【系统搭建】DPDK关键概念与l2fwd源码解析
DPDK(Data Plane Development Kit)是一套用于高性能网络数据面处理的开发框架,其核心设计在于绕过内核协议栈,它提供了一个用户空间下的高效数据包处理库函数,可以用于快速开发高性能的网络应用程序,如网络…...
【Qt】初识Qt(一)
目录 一、Qt的背景二、认识Qt项目 一、Qt的背景 关于客户端开发: 客户端开发的重要任务,是编写和用户交互的界面,和用户交互的界面有两种风格: TUI:命令行界面,也叫终端界面GUI:图形化界面 Q…...
Django REST framework 并结合 `mixin` 的示例
下面为你提供一个使用 Django REST framework 并结合 mixin 的示例,该示例将实现一个简单的图书管理 API。 项目需求 我们要创建一个图书管理系统的 API,支持对图书信息的创建、读取、更新和删除操作。 实现步骤 1. 项目初始化 首先,确保你已经安装了 Django 和 Django…...
《前端性能优化秘籍:打造极致用户体验》
在当下,网站和应用的性能表现直接关乎用户去留。快速加载、流畅交互的页面能让用户沉浸其中,反之,缓慢的响应速度则会让他们毫不犹豫地离开。对于前端开发者而言,性能优化不仅是技术追求,更是提升用户体验、增强产品竞…...
数据结构与算法学习导航
目录 指导思想资料总结代码随想录hello-algoOI-WIKI 一名麻瓜的刷leetcode的简单概述。 在这里对过去的自己说: 如果你相信算法有用你就刷刷leetcode,如果不相信面试会让你相信。 当然,现在我确实认为算法和数据结构有用,leetcode也有用。 …...
【Python】用Python写一个俄罗斯方块玩玩
【Python】用Python写一个俄罗斯方块玩玩 一、引言1.成品效果展示 二、思考准备1.思考设计2.代码设计2.1 游戏页面2.2 控件设计2.2.1 方块生成2.2.2 方块碰撞2.2.3 方块消融2.2.4 游戏主循环2.2.5 游戏窗口 三、游戏完整版 一、引言 今日看到侄子在玩游戏,凑近一看…...
nginx中的代理缓存
1.缓存存放路径 对key取哈希值之后,设置cache内容,然后得到的哈希值的倒数第一位作为第一个子目录,倒数第三位和倒数第二位组成的字符串作为第二个子目录,如图。 proxy_cache_path /xxxx/ levels1:2 2.文件名哈希值...
【深度学习】详解矩阵乘法、点积,内积,外积、哈达玛积极其应用|tensor系列02
博主简介:努力学习的22级计算机科学与技术本科生一枚🌸博主主页: Yaoyao2024往期回顾:【深度学习】你真的理解张量了吗?|标量、向量、矩阵、张量的秩|01每日一言🌼: “脑袋想不明白的,就用脚想”…...
20.3 使用技巧3
版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的 20.3.5 禁止追加行与禁止删除行 通常情况下DataGridView最末一行是空白行,在此行单元格输入数据就可以追加新行。如果需要…...
使用代理IP提取数据的步骤是什么?代理IP如何提高爬虫采集效率?
在当今大数据时代,网络爬虫已成为获取互联网信息的重要手段。然而,许多网站为了防止数据被过度抓取,会设置反爬机制,如IP封禁、访问频率限制等。这时,使用代理IP就成为了一种有效的解决方案。本文将详细介绍使用代理IP…...
探索关系型数据库 MySQL
目录 引言 一.SQL的基本操作 1.数据库是什么? 什么是SQL? 1.1.OLTP 1.2.OLAP 1.3.SQL 1.4.DQL 1.5.DML 1.6.DDL 1.7.DCL 1.8.TCL 1.9.数据库术语 2.MySQL体系结构 2.1.连接者 2.2.MySQL 内部连接池 2.3.管理服务和工具组件 2.4.SQL接口 …...
Redis--事务
目录 一、事务介绍 二、事务操作 2.1 MULTI 2.2 EXEC 2.3 DISCARD 2.4 WATCH 2.5 UNWATCH 一、事务介绍 Redis 的事务和 MySQL 的事务概念上是类似的. 都是把一系列操作绑定成⼀组. 让这⼀组能够批量执行. 但是注意体会 Redis 的事务和 MySQL 事务的区别: 1.弱化的原子性…...
【Windows上配置Git环境】
在Windows上配置Git环境可以按照以下步骤进行: 1. 下载Git 打开浏览器,访问Git官方网站https://git-scm.com/downloads。在下载页面中,找到适用于Windows的下载链接,根据你的系统是32位还是64位选择相应的安装包进行下载 。 2.…...
揭秘大数据 | 23、软件定义网络
软件定义网络将网络的边缘从硬件交换机推进到了服务器里面,将服务器和虚拟机的所有部署、管理的职能从原来的系统管理员网络管理员的模式变成了纯系统管理员的模式,让服务器的业务部署变得简单,不再依赖于形态和功能各异的硬件交换机…...
前端api(请求后端)简易template
微信小程序 API 模块模板 基本 API 模块结构 /*** 示例API模块*/ const api require(../api); const config require(../../config/index);// 示例API对象 const exampleApi {// API方法定义... };// 导出模块 module.exports exampleApi;标准 RESTful 请求方法 获取列表…...
【力扣】重排链表
重排链表 代码 class Solution { public:void reorderList(ListNode* head) {//当链表只有一个节点或两个节点时直接返回空,不用重排if (head->next NULL || head->next->next NULL) return;//1. 进行分割链表ListNode* fast head, *slow head;ListNode* end1 N…...
选 Hibernate 还是 MyBatis?全方位差异解读
Hibernate 和 MyBatis 都是 Java 开发中用于处理数据库操作的持久化框架,不过它们在实现技术上存在诸多差异,下面从多个方面进行对比: 1. 映射机制 Hibernate:采用全自动的对象关系映射(ORM)机制…...
SvelteKit 最新中文文档教程(21)—— 最佳实践之图片
前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。 从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1: Svelte …...
类和对象(下篇)(详解)
【本节目标】 1. 再谈构造函数 2. Static成员 3. 友元 4. 内部类 5. 再次理解封装 1. 再谈构造函数 1.1 构造函数体赋值 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。 #include <iostream> using name…...
win10下github libiec61850库编译调试sntp_example
libiec61850 https://github.com/mz-automation/libiec61850 v1.6 简介 libiec61850 是一个开源(GPLv3)的 IEC 61850 客户端和服务器库实现,支持 MMS、GOOSE 和 SV 协议。它使用 C 语言(根据 C99 标准)实现…...
【HDFS入门】HDFS高可用性与容错机制深度解析
目录 引言 1 HDFS高可用架构实现 1.1 基于QJM的NameNode HA架构 1.2 QJM vs NFS实现对比 2 故障切换流程与ZooKeeper作用 2.1 自动故障转移流程 2.2 状态转换机制 3 数据恢复与副本管理 3.1 DataNode故障处理流程 4 快照与数据保护机制 4.1 HDFS快照架构 4.2 快照使…...
Qt QML实现Windows桌面歌词动态播放效果
前言 使用Qt5.15.2,QML实现简单的歌词动态播放效果。 效果图如下: 注:这里只是为了演示播放效果,并未真正加载音频进行播放。可以在此基础上进行扩展。 正文 关键代码 QML部分 import QtQuick 2.15 import QtQuick.Window 2.…...
Qt GUI 库总结
Qt GUI 库总结 Qt GUI 库(QtGui)是 Qt 框架中负责图形用户界面(GUI)开发的核心模块。本文将一步步详解 QtGui,从基础入门到高级应用,帮助你全面掌握其功能。以下内容包括环境配置、基本功能、核心特性及进…...
[dp16_两个数组] 通配符匹配 | 交错字符串 | 两个字符串的最小ASCII删除和
目录 1.通配符匹配 题解 2.交错字符串 题解 3.两个字符串的最小ASCII删除和 1.通配符匹配 链接:44. 通配符匹配 给你一个输入字符串 (s) 和一个字符模式 (p) ,请你实现一个支持 ? 和 * 匹配规则的通配符匹配: ? 可以匹配任何单个字…...
记录一次生产中mysql主备延迟问题处理
登录库: mysql -uXXXX -pXXXX -P3306 -hXXXXXX -A 备库上执行:show slave status\G 查看 seconds_Behind_Master,延迟 2705s,而且还一直在增加。 SHOW CREATE TABLE proc_i_income_temp; -- 查看表的结构 show index from proc…...
【计算机视觉】OpenCV实战项目-AdvancedLaneDetection 车道检测
AdvancedLaneDetection 项目解析 项目概述项目结构功能和步骤依赖项使用方法项目特点改进建议结论运行项目1. 克隆项目仓库2. 安装依赖项创建虚拟环境(可选)激活虚拟环境安装依赖项 3. 准备数据4. 运行项目5. 调整配置(可选)6. 查…...
趣味编程之分布式系统:负载均衡的“雨露均沾“艺术
#此篇文章由Deepseek大力支持😋 凌晨三点,西二旗某火锅店后厨—— “羊肉卷走3号桌!” “肥牛卷去7号!” “虾滑优先给VIP区!” 我蹲在传菜口的监控屏幕前,看着机器人服务生们忙而不乱地穿梭。突然间&am…...
移植firefly core-1126-jd4官方sdk源码到其他rv1126板卡时 kernel启动中失去响应问题解决
问题背景 在项目中采用firefly core-1126-jd4的sdk适配其他rv1126板卡遇到kernel启动中无响应。串口能看到运行到usb、mmc等模块驱动流程,但之后就打印,通过追加打印确认usb、mmc模块的init已经执行完,怀疑是执行其他某个静态编译进kernel的…...
Oracle表的别名不能用as,列的别名可以用as
在 Oracle 数据库中,表的别名和列的别名在使用 AS 关键字时确实有不同规则,以下是详细说明: 1. 表的别名(Table Alias) 不支持 AS 关键字,直接跟在表名后即可。语法示例: S…...
对于“人工智能+教育”的一些思考
如果说人工智能当下最合适的落地场景,那么进入课堂这件事一定是排在靠前的位置。从当下的趋势来看,人工智能进入课堂已经不是设想,而是我们必须要去做的一件事了。 方向有了,但是问题是:人工智能进入中小学课堂到底应该…...
Android audio系统四 audiopolicy与audioflinger播放和录音
播放/录音在上层是通过AudioTrack与AudioRecord实现的。通过一张简单的流程图查看audiopolicy与audioflinger进行了哪些操作...
【Pandas】pandas DataFrame xs
Pandas2.2 DataFrame Indexing, iteration 方法描述DataFrame.head([n])用于返回 DataFrame 的前几行DataFrame.at快速访问和修改 DataFrame 中单个值的方法DataFrame.iat快速访问和修改 DataFrame 中单个值的方法DataFrame.loc用于基于标签(行标签和列标签&#…...
开源一体化白板工具Drawnix本地部署打造毫秒级响应的远程协作空间
文章目录 前言1、什么是Drawnix?2、部署Drawnix的环境和步骤3、Drawnix的简单使用方法4、安装cpolar内网穿透5、配置公网地址6、配置固定二级子域名公网地址总结 前言 想象一下,你是一个创意满满的设计师,脑海中涌现出无数灵感火花。你急忙打…...
UMAEA论文阅读
Preliminaries MMKG为一个五元组G{E, R, A, V, T},其中E、R、A和V分别表示实体集、关系集、属性集和图像集。 T⊆ERE是关系三元组集。 给定两个MMKG G1 {E1, R1, A1, V1, T1} 和 G2 {E2, R2, A2, V2, T2}, MMEA旨在识别每个实体对(e1…...
捕鱼船检测数据集VOC+YOLO格式2105张1类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2105 标注数量(xml文件个数):2105 标注数量(txt文件个数):2105 …...
R4打卡——pytorch实现LSTM预测火灾
🍨 本文为🔗365天深度学习训练营中的学习记录博客 🍖 原作者:K同学啊 1.检查GPU import torch.nn.functional as F import numpy as np import pandas as pd import torch from torch import nndata pd.read_csv("da…...
【数字图像处理】图像增强
图像增强——频率域分析 卷积定理 函数卷积的傅里叶变换是函数傅里叶变换的乘积,即:一个域中的卷积相当于另一个域中的乘积 F(x)为傅里叶变换 傅里叶 傅里叶级数:任何周期函数都可以用不同频率的正弦函数和余弦函数构成的无穷级数来表示。 正…...
Windows平台用vistual studio 2017打包制作C++动态库
1. 创建库项目 打开 Visual Studio 2017,选择 文件 → 新建 → 项目。选择 Visual C → Windows 桌面 → 动态链接库 (DLL) 或 静态库 (LIB)。 动态库 (DLL):生成 .dll 和 .lib(导出符号表)。静态库 (LIB):生成 .lib&…...
QT日历控件重写美化
效果图 先放一个效果图以供大家参考,大家可以根据自己需要的效果来调整自己的控件,日历控件实现了自定义日历选择框,设置了表头颜色,设置日历当天重要事件提醒功能。 设置表头样式 setVerticalHeaderFormat(QCalendarWidget::NoV…...
单细胞分析读取处理大型数十万细胞的数据集的优化
单细胞分析读取处理大型数十万细胞的数据集的优化 背景简介 有朋友反映用自己的笔记本电脑在分析比较大的单细胞数据集的时候,比如细胞数量有十万个以上甚至几十万个的时候,可能自己的电脑的内存32G或64G都不够用,一般来说,做生…...
HTTP 3.0 协议的特点
HTTP/3 是互联网传输协议的一次重要升级,相较于 HTTP/2,它引入了多项显著改进和新特性。 基于 QUIC 协议: HTTP/3 采用了 QUIC(Quick UDP Internet Connections)作为底层传输协议,QUIC 基于 UDP࿰…...
电子电器架构 --- 下一代汽车电子/电气(E/E)架构
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁&am…...
08软件测试需求分析案例-删除用户
删除用户是后台管理菜单的一个功能模块,只有admin才有删除用户的权限。不可删除admin。 1.1 通读文档 通读需求规格说明书是提取信息,提出问题,输出具有逻辑、规则、流程的业务步骤。 信息:此功能应为用户提供确认删除的功能。…...
await 在多线程,子线程中的使用
await 在多线程,子线程中的使用 await self.send_reply(user, user, user, auto_content, reply) 这行代码是在一个异步函数里调用类的实例方法 send_reply 代码含义 1. await 关键字 在 Python 的异步编程里,await 关键字的作用是暂停当前异步函数的执行,直到 await 后…...
NLP高频面试题(四十六)——Transformer 架构中的位置编码及其演化详解
引言 Transformer 模型(Vaswani 等人,2017)在序列建模中取得了革命性突破,利用自注意力机制实现了并行的序列处理。然而,Transformer 本身对序列的顺序信息不敏感:输入序列元素在自注意力中是无排列的(Permutation-invariant)。换言之,Transformer 缺乏像 RNN 那样的…...
C++笔记-list
list即是我们之前学的链表,这篇主要还是讲解list的底层实现,前面会讲一些list区别于前面string和vector的一些接口以及它们的注意事项。 一.list的基本使用 和之前的string,vector一样,有很多之前见过的一些接口,经过…...