归并排序和分治

归并排序

归并排序是利用归并的思想实现的排序方法,该算法采用经典的分治策略(分治法将问题成一些小的问题然后递归求解,而的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。

分而治之

可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现)。

过程:左部分排好序,右部分排好序,利用merge过程让左右整体有序(merge过程:谁小拷贝谁,直到左右两部分所有的数字耗尽)

归并排序算法有两个基本的操作,一个是,也就是把原数组划分成两个子数组的过程。另一个是,它将两个有序数组合并成一个更大的有序数组。

  1. 将待排序的线性表不断地切分成若干个子表,直到每个子表只包含一个元素,这时,可以认为只包含一个元素的子表是有序表。
  2. 将子表两两合并,每合并一次,就会产生一个新的且更长的有序表,重复这一步骤,直到最后只剩下一个子表,这个子表就是排好序的线性表。

阶段

可以理解为就是递归拆分子序列的过程,利用二分法

递归深度为log2n。

合并两个有序数组流程

再来看看阶段,我们需要将两个已经有序的子序列合并成一个有序序列,比如上图中的最后一次合并,要将[4,5,7,8]和[1,2,3,6]两个已经有序的子序列,合并为最终序列[1,2,3,4,5,6,7,8],来看下实现步骤。

代码:

# include <stdio.h>

int arr[100];
inr help[100];

int n;

void mergesort(int l, int r)
{
	if (l == r)
		return;
	
	int m = (l+r) / 2;
	mergesort(l, m);
	mergesort(m+1, r);
	merge(l, m, r); //让左右整体有序 
}

//让 l 到 r 变 有序
//把[l, m] 和 [m+1, r]进行合并 
void merge(int l, int m, int r)
{
	int i = l;
	int a = l;
	int b = m+1; 
	while (a <= m && b <=r)
	{
		if (arr[a] <= arr[b])
		{
			help[i] = arr[a];
			a = a + 1;
		}
		else
		{
			help[i] = arr[b];
			b = b + 1;
		}
		i = i + 1;
	}
	//左侧指针,右侧指针,必有一个越界,另一个不越界
	while (a <= m)
	{
		help[i] = a;
		i = i + 1;
		a = a + 1;
	} 
	while (b <= r)
	{
		help[i] = b;
		i = i + 1;
		b = b + 1;
	} 	
	for (int i=l; i<=r; ++i)
	{
		arr[i] = help[i];
	}
}

int main()
{
	scanf("%d", &n);
	for (int i=0; i<n; ++i)
		scanf("%d", &arr[i]);
		
	mergesort(0, n-1);

}

归并分治



问题一

本题发现

符合第一个原理

在计算跨越左右产生的答案时,我们发现如果左、右各有序,则会提高计算便利性

因此就可以考虑归并分治

代码:

# include <stdio.h>

int arr[100];
int help[100];

int n;

int sum(int l, int r)
{
	if (l == r)
		return 0;
	int m = (l + r) / 2;
	return sum(l, m) + sum(m+1, r) + merge(l, m, r);
}

int merge(int l, int m, int r)
{
	int ans = 0;
	int j = l;
	int sum = 0;
	for (int i=m+1; i<r; ++i)
	{
		while (j <= m && arr[i] >= arr[j])
		{
			sum = sum + arr[j];
			j = j + 1;
		}
		ans = ans + sum;
	}
	int i = l;
	int a = l;
	int b = m + 1;
	while (a <= m && b <=r)
	{
		if (arr[a] <= arr[b])
		{
			help[i] = arr[a];
			a = a + 1;
		}
		else
		{
			help[i] = arr[b];
			b = b + 1;
		}
		i = i + 1;
	}
	//左侧指针,右侧指针,必有一个越界,另一个不越界
	while (a <= m)
	{
		help[i] = a;
		i = i + 1;
		a = a + 1;
	} 
	while (b <= r)
	{
		help[i] = b;
		i = i + 1;
		b = b + 1;
	} 	
	for (int i=l; i<=r; ++i)
	{
		arr[i] = help[i];
	}
}

int main()
{
	scanf("%d", &n);
	for (int i=0; i<n; ++i)
		scanf("%d", &arr[i]);
	int ans = sum(0, n-1);
	
}

问题二

符合第一个原理

在计算跨越左右产生的答案时,我们发现如果左、右各有序,则会提高计算便利性

因此就可以考虑归并分治

代码:

# include <stdio.h>

int arr[100];
int help[100];

int n;

int cmp(int l, int r)
{
	if (l == r)
		return 0;
	int m = (l+r) / 2;
	return cmp(l, m) + cmp(m+1, r) + merge(l, m, r);
}

int merge(int l, int m, int r)
{
	int j = l;
	int q = m+1;
	int sum = 0;
	int ans = 0;
	for (int i=l; i<=m; ++i)
	{
		while (q <= r && arr[i] > arr[q] * 2)
		{
			q = q + 1;
		}
		ans = ans + (q - m - 1) - i;
	}
	int x = l;
	int a = l;
	int b = m + 1;
	while (a <= m && b <=r)
	{
		if (arr[a] <= arr[b])
		{
			help[x] = arr[a];
			a = a + 1;
		}
		else
		{
			help[x] = arr[b];
			b = b + 1;
		}
		x = x + 1;
	}
	//左侧指针,右侧指针,必有一个越界,另一个不越界
	while (a <= m)
	{
		help[x] = a;
		x = x + 1;
		a = a + 1;
	} 
	while (b <= r)
	{
		help[x] = b;
		x = x + 1;
		b = b + 1;
	} 	
	for (int i=l; i<=r; ++i)
	{
		arr[i] = help[i];
	}
	return ans;
}



int main()
{
	scanf("%d", &n);
	for (int i=0; i<n; ++i)
		scanf("%d", &arr[i]);
		
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode-142. 环形链表 II【哈希表 链表 双指针】

LeetCode-142. 环形链表 II【哈希表 链表 双指针】 题目描述&#xff1a;解题思路一&#xff1a;快慢指针 判断是否有环见解题思路二&#xff1a;set()解题思路三&#xff1a;0 题目描述&#xff1a; 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如…

The Sandbox 与 Otherworld 合作推出元宇宙网络漫画中心

​ The Sandbox 将与韩国初创公司 Otherworld 合作&#xff0c;建立一个元宇宙网络动漫中心&#xff0c;为用户提供基于 KakaoPage 热门 IP 的各种体验。 Solo Leveling 是此次合作的第一个 IP。这部网络动画将深入主人公Sung Jinwoo的生活&#xff0c;并与 NFT 进行整合。随后…

面试算法-122-翻转二叉树

题目 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1] 解 class Solution {public TreeNode invertTree(TreeNode root) {return dfs(…

SpringBoot项目启动成功,但是调用接口直接报NOT FOUND 404

问题描述 SpringBoot项目启动成功&#xff0c;但是调用接口直接报NOT FOUND 404 解决办法 启动类中ComponentScan(basePackages {“com.afclab”})中的扫包路径和项目路径不一样&#xff0c;导致扫不到Controller等组件&#xff0c;修改成和项目路径一样就可以解决&#xf…

科技团队治理能力成长路线图

点击&#x1f446;蓝字 关注我们 本文观点&#xff5c;吴穹 主笔&#xff5c;AI小助手 温馨提示&#xff1a;干货长文&#xff0c;建议收藏阅读喔&#xff5e; 引言 2024年3月20日&#xff0c;吴穹博士于上海交通大学上海高级金融学院同一众信托行业金融科技管理者进行了《金融…

Postman和Python Request测试多行Form-data

1、请求参数有多个&#xff0c;F12查看请求体如下&#xff1a; 查看源代码&#xff1a; ------WebKitFormBoundaryHknGXm9VkhRUXZYC Content-Disposition: form-data; name"custId"IICON004 ------WebKitFormBoundaryHknGXm9VkhRUXZYC Content-Disposition: form-da…

尚硅谷2024最新Git企业实战教程 | Git与GitLab的企业实战

这篇博客是尚硅谷2024最新Git企业实战教程&#xff0c;全方位学习git与gitlab的完整笔记。 这不仅仅是一套Git的入门教程&#xff0c;更是全方位的极狐GitLab企业任务流开发实战&#xff01;作为一应俱全的一站式DevOps平台&#xff0c;极狐GitLab的高阶功能全面覆盖&#xff0…

LangSmith

文章目录 关于 LangSmith创建 API Key 基本代码使用查看控制台 关于 LangSmith 主页&#xff1a;https://www.langchain.com/langsmith文档&#xff1a;https://docs.smith.langchain.com/LangSmith Walkthrough &#xff1a; https://python.langchain.com/docs/langsmith/wa…

Java就近原则和this关键字

Java 中的就近原则和 this 关键字有着密切的关系&#xff0c;特别是在处理成员变量与方法参数同名的情况下。就近原则指的是在同一作用域下&#xff0c;优先使用最近声明的变量或参数。 在 Java 中&#xff0c;如果一个方法的参数与类的成员变量同名&#xff0c;为了明确指示要…

上网行为管理系统推荐,上网行为审计软件推荐

上网行为管理是指帮助互联网用户控制和管理对互联网的使用。它涵盖了多个方面&#xff0c;包括网页访问过滤、上网隐私保护、网络应用控制、带宽流量管理、信息收发审计、用户行为分析等。 上网行为管理产品系列适用于需要实施内容审计与行为监控、行为管理的网络环境&#xf…

Day29代码随想录(1刷) 回溯

51. N 皇后 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;返回所有不同的 n 皇后问题 的解决方案…

数据恢复工具可以恢复所有丢失的文件吗

随着数字时代的快速发展&#xff0c;数据已经成为我们生活与工作中不可或缺的一部分。然而&#xff0c;数据丢失的风险也随之增大。无论是由于误删除、误格式化、病毒感染还是其他意外情况&#xff0c;数据丢失都可能带来不小的损失。在这种情况下&#xff0c;数据恢复工具应运…

【SQL】1873. 计算特殊奖金(CASE WHEN;IF())

题目描述 leetcode题目&#xff1a;1873. 计算特殊奖金 Code 写法一&#xff1a; CASE WHEN select employee_id, (case when employee_id % 2 0 or name like M% then salary 0 else salary end) as bonus from Employees order by employee_id写法二 &#xff1a;IF() …

使用deepspeed小记

1. 减少显存占用的历程忠告 医学图像经常很大&#xff0c;所以训练模型有时候会有难度&#xff0c;但是现在找到了很多减少显存的方法。 不知道为什么&#xff0c;使用transformers的trainer库确确实实会减少显存的占用&#xff0c;即使没有使用deepspeed&#xff0c;占用的显…

【QT学习】4.浮动窗口

结果&#xff1a; 代码&#xff1a; //制作核心控件&#xff1a;文本编辑框QTextEdit* pTextEditnew QTextEdit;//制作浮动控件connect(pMenu1,&QMenu::triggered,[](QAction* pAction){qDebug()<<pAction->text()<<endl;if(pAction->text()"浮动…

若依框架时间比较的坑(DATE_FORMAT)

背景 - 想做生日的比较 若依自带的比较 <if test"params.beginTime ! null and params.beginTime ! "><!-- 开始时间检索 -->AND date_format(u.create_time,%y%m%d) > date_format(#{params.beginTime},%y%m%d)</if><if test"params…

XXLJob中GLUE模式实现在线编写java/shell/python/php/nodejs/powerShell---SpringCloud工作笔记202

1.起因: 之前就一直想实现类似的功能,今天总于找到有可以参考的东西了,这个思路可以帮助实现这种功能. 2.获得灵感 就是:我想实现通过在线编写代码,来扩展我们平台的能力,这样随着业务的扩展,不用我们每次都修改了代码,再去部署,这样就比较麻烦,今天偶尔发现,对于xxljob来说.有…

QA测试开发工程师面试题满分问答8: mysql数据库的索引定义、用途和使用场景

MySQL数据库索引是一种数据结构&#xff0c;用于提高数据库的查询效率。索引是基于表中的一个或多个列构建的&#xff0c;它们允许数据库系统快速定位和访问表中的特定数据&#xff0c;而无需扫描整个表。 索引的定义 在MySQL中&#xff0c;可以使用CREATE INDEX语句定义索引…

计算机网络|谢希仁版|数据链路层

数据链路层 数据链路层研究的是什么&#xff1f;数据链路层的几个共同问题数据链路与链路帧通信规程 三个基本问题封装成帧透明传输差错检测可靠传输 点对点协议PPPPPP协议应满足的需求PPP协议的组成PPP协议帧的格式各字段的意义字节填充零比特填充PPP协议的工作状态 使用广播信…

TSINGSEE青犀推出河道/河湖/水域治理视频AI智能解决方案

一、方案背景 “十四五”时期&#xff0c;在面源污染防治等方面实现突破&#xff0c;实现主要水污染排放总量持续减少&#xff0c;水生态环境持续改善等任务艰巨。进一步完善流域综合治理体系&#xff0c;提升流域水环境综合治理能力和水平&#xff0c;更好适应新阶段发展需求…