各类排序方法 归并排序 扩展练习 逆序对数量

news2024/12/24 2:20:39

七月挑战一个月重刷完Y总算法基础题,并且每道题写详细题解

进度:(3/106) 

归并排序的思想也是分而治之

归并优点:速度稳定,排序也稳定

排序也稳定(数组中有两个一样的值,排序之后他们的前后顺序不发生变化,我们就说这个排序是稳定的)

缺点:比起快排,空间复杂度更高

使用场景:数据量巨大,寻求稳定

速度:稳定n(logn)

思想思路

第一步

找分界点(mid,中间值)

第二步

先递归排序两边

第三步

将两个有序数组合二为一(归并)

有序数组合并实现思路(归并)

利用双指针

准备三个数组和两个指针

三个数组其中两个是有序数组,一个是准备用来存储的

#include<iostream>
#include<algorithm>
using namespace std;
int n,arr[10000010],sum[10000010];
void m_sort(int arr[],int l,int r){
    //到达边界,退出
    if(l>=r)return;
    //找到分界点
    int mid=(l+r)>>1;
    //利用分界点分成两个数组,递归两个数组
    m_sort(arr,l,mid),m_sort(arr,mid+1,r);
    //上面递归结束的,一定是两段有序数组
    //遍历两个数组,把两个数组的值,按照归并顺序放到第三暂存个数组
    //这个两个数组,其实指的是一个数组上的两个有序区间
    //每次放入之前,先进行比较两个数组里的指针指向的数
    //谁指向的数组元素小,先放谁进入第三个暂存数组
    //然后那个数组的指针指向下个元素,循环往复,直至其中一个数组遍历完毕
    int i=l,j=mid+1,k=0;
    while(i<=mid&&j<=r){
        if(arr[i]<arr[j])sum[k++]=arr[i++];
        else sum[k++]=arr[j++];
    }
    //上面的循环只保证其中一个数组遍历完毕
    //下面的两个循环,把未遍历完毕的那个数组剩下的元素,添加进暂存数组
    while(i<=mid)sum[k++]=arr[i++];
     while(j<=r)sum[k++]=arr[j++];
     //把暂存数组,放入原数组,替代原数组元素,完成对arr[l-r]的排序
     for(int i=l,j=0;i<=r&&j<=k; i++,j++){
         arr[i]=sum[j]; 
     }
}
int main(){
    cin>>n;
    for(int i=0;i<n;i++)cin>>arr[i];
    m_sort(arr,0,n-1);
    for(int i=0;i<n;i++)cout<<arr[i]<<' ';
    return 0;
}

归并排序已完成

感悟思想:归并排序思想也是分而治之,但是和快排不同的是,快排是把大的放左边,小的放右边后

越递归,数组有序性越强,先分好再递归,归并排序是先递归,再排序

先确定下标的中间,中位点的下标,也就是数组长度是十的话,中位点的下标就是5

然后直接就分别递归中位点的左边和右边

直到数组变成一位的时候,递归停止,开始回溯

回溯到数组是两位的时候,现在的中位点左右两边,都是有序数组,只需要用两个指针,各指向两个数组

把小的,先放入新数组即可,后面同理,回溯时,中位点两边的数组一定都是有序数组

把两个有序数组合并成新数组,只需要使用双指针,把指向的数组的值较小的那个放入新数组,然后右移指针即可

直到回溯完毕,最后一次合并,原来的无序数组就排好了

有人叫回溯是回归,回归+合并,归并排序。

经典题:逆序对的数量

题目

活动 - AcWing

思路

用分治的思想,mid将数组分成=两段

则逆序对只有三种可能:

红色,同时在左半边,绿色,同时在右半边,黄色,一半在左一半在右

我们先解决黄色情况

假设数组a[n],数组b[n]都是两个有序数组,且a[n]就是mid前0到mid的子串,b[n]是mid后mid+1到r的子串

使用双指针算法,i,j分别指向数组第一个元素

a[i]和b[j]逐位比较

一旦b[j]小于a[i]中一个数,那说明,i到mid所有数,都和b[j]组成逆序对

因为a[]数组有序,a[i]到a[mid]的数必大于a[i],也就必大于b[j],也就必和b[j]组成逆序对

那我们只需要在两者归并排序时,累加记录res+=mid-i+1;

res便是这两个有序数组里的逆序对个数

(mid就是a[n]的长度,-i是减去已经指向过的数,+1是因为i从0开始)

黄色情况可以解决了,那只需要把所有情况都递归分割成黄色情况,所有情况都解决了

结论,只需要在归并排序时,累加记录arr[j]放在arr[i]前的情况时mid-(i+1)的值

代码

这里只对改动部分注释,看归并排序点这归并排序

#include<iostream>
using namespace std;
//数可能很大,使用long long
typedef long long ll;
int a[100010],s[100010];
ll add(int a[],int l,int r){
    if(l>=r)return 0;
    int mid=l+r>>1;
    //res接收值
    ll res=add(a,l,mid);
    //第二段的加上第一段的
    res+=add(a,mid+1,r);
    int k=0,i=l,j=mid+1;
    while(i<=mid&&j<=r){
        if(a[i]<=a[j])s[k++]=a[i++];
        else{
            //一旦a[j]需要放在a[i]前面
            //说明a[j]和a[i]以及a[i]到a[mid]所有数,都组成逆序对
            //mid-(i+1)的结果,就是a[i]到a[mid]的数的个数(+1是因为i从0开始)
            //每次出现这个时,把这个结果累加即可
            res+=mid-i+1;
            s[k++]=a[j++];
        }
    }
    while(i<=mid)s[k++]=a[i++];
    while(j<=r)s[k++]=a[j++];
    for(int i=0,j=l;j<=r;j++,i++){
        a[j]=s[i];
    }
    //处理完这段l-r,把res结果返回出去,处理下一段l-r
        return res;
}
int main(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>a[i];
    }
       ll res=add(a,0,n-1);
       cout<<res<<endl;
    return 0;
}

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

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

相关文章

一句话介绍什么是AI智能体?

什么是AI智能体&#xff1f; 一句话说就是利用各种AI的功能的api组合&#xff0c;完成你想要的结果。 例如你希望完成一个关于主题为啤酒主题的小红书文案图片&#xff0c;那么它就可以完成 前面几个步骤类似automa的组件&#xff0c;最后生成一个结果。

手把手搞定报名亚马逊科技认证

引言 亚马逊云科技认证考试为我们这些技术从业者提供了提升专业技能的机会。无论选择线上还是线下考试&#xff0c;每种方式都有其独特的优势和挑战。选择合适的考试方式将帮助我们更好地展示自己的技术水平。以下是我对不同考试方式的优缺点介绍&#xff0c;以及各科目的考试…

tkinter显示图片

tkinter显示图片 效果代码解析打开和显示图像 代码 效果 代码解析 打开和显示图像 def open_image():file_path filedialog.askopenfilename(title"选择图片", filetypes(("PNG文件", "*.png"), ("JPEG文件", "*.jpg;*.jpeg&q…

哈希表(C++实现)

文章目录 写在前面1. 哈希概念2. 哈希冲突3. 哈希函数4.哈希冲突解决4.1 闭散列4.1.1 线性探测4.1.2 采用线性探测的方式解决哈希冲突实现哈希表4.1.3 二次探测 4.2 开散列4.2.2 采用链地址法的方式解决哈希冲突实现哈希表 写在前面 在我们之前实现的所有数据结构中(比如&…

CesiumJS【Basic】- #042 绘制纹理线(Primitive方式)

文章目录 绘制纹理线(Primitive方式)1 目标2 代码2.1 main.ts3 资源文件绘制纹理线(Primitive方式) 1 目标 使用Primitive方式绘制纹理线 2 代码 2.1 main.ts var start = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);var

爬虫逆向实战(41)-某巢登陆(AES、MD5、RSA、滑块验证码)

一、数据接口分析 主页地址&#xff1a;某巢 1、抓包 通过抓包可以发现在登录时&#xff0c;网站首先请求captcha/querySlideImage/来获取滑块验证码的图片&#xff0c;然后请求captcha/checkCode/接口来验证滑块验证码。滑块验证码校验成功后&#xff0c;请求noshiro/getPu…

使用explain优化慢查询的业务场景分析

问&#xff1a;你最害怕的事情是什么&#xff1f;答&#xff1a;搓澡问&#xff1a;为什么&#xff1f;答&#xff1a;因为有些人一旦错过&#xff0c;就不在了 Explain 这个词在不同的上下文中有不同的含义。在数据库查询优化的上下文中&#xff0c;“EXPLAIN” 是一个常用的 …

矩阵置零解题

给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]]示例 2&#xff1a; 输入&…

UI(四)布局

文章目录 10、Navigator——路由器组件11、Pannel——可滑动面板12、Refresh——刷新组件13、RelativeContainer——相对布局组件14、Scroll——可滚动容器15、SideBarContainer——侧边栏容器16、Stack——堆叠容器17、Swiper——滑动块视图容器18、Tabs和TabContent——页签和…

mac英语学习工具:Eudic欧路词典 for Mac 激活版

Eudic欧路词典是一款非常受欢迎的英语学习软件&#xff0c;它提供了丰富的词汇解释、例句、同义词、反义词等功能&#xff0c;帮助用户更好地理解和掌握英语单词。 以下是Eudic欧路词典的一些主要特点&#xff1a; 海量词汇库&#xff1a;Eudic欧路词典拥有庞大的词汇库&#…

arm_uart4实验

#include "uart4.h" //UART //初始化 void hal_uart4_init() { //rcc_init //…

Google推出开源模型Gemma 2:性能大幅提升与创新训练方法

引言 近日&#xff0c;Google推出了开源模型Gemma 2&#xff0c;吸引了广大研究人员和开发者的关注。相比上一代模型&#xff0c;Gemma 2在性能和可用性方面实现了显著提升&#xff0c;提供了9B和27B两个版本&#xff0c;并且对外开放免费使用。本文将深入探讨Gemma 2的技术细…

QueryClientProvider is not defined

QueryClientProvider is not defined 运行一个svelte的项目&#xff0c;报错如上&#xff0c;前后查找解决不了&#xff0c;然后没办法&#xff0c; 本来是用yarn 安装的依赖&#xff0c;改用npm install&#xff0c;再次运行就成功了

可燃气体报警器定期检测:优化与改进策略的探讨

在现代化的工业环境中&#xff0c;可燃气体报警器的作用日益凸显。它们像是我们生产现场的安全卫士&#xff0c;时刻警惕着可能发生的危险&#xff0c;确保我们的工作环境安全、稳定。 然而&#xff0c;要确保这些“卫士”始终忠诚可靠&#xff0c;定期检测就显得尤为重要。 …

【JVM面试题】总结-01

【JVM面试题】总结-01 1. 介绍下Java内存区域(运行时数据区)1.1 程序计数器(线程私有)1.2 虚拟机栈(线程私有)1.3 本地方法栈(线程私有)1.4 Java堆(线程共享)1.5 方法区(线程共享)1.5.1 方法区和永久代的关系1.5.2 常用参数1.5.3 为什么要将永久代 (方法区) 替换为元空间 (Meta…

WCCI 2024开幕,横滨圣地巡礼,畅游动漫与美食的世界

惊喜&#xff01;WCCI 2024开幕&#xff0c;横滨圣地巡礼&#xff01;畅游动漫与美食的世界 会议之眼 快讯 会议介绍 IEEE WCCI&#xff08;World Congress on Computational Intelligence&#xff09;2024&#xff0c;即2024年IEEE世界计算智能大会&#xff0c;于6月30日至…

写代码,为什么还需要作图?

引言 古人云 &#xff1a;一图胜千言&#xff0c;闲人说&#xff1a;无图无真相。 在日常的聊天工具当中&#xff0c;无论是使用微信&#xff0c;还是钉钉。使用图片或表情包的频次越来越高&#xff0c;那是为什么呢&#xff1f;其实在互联网没有那么发达的时候&#xff0c;我…

Adobe Premiere 视频编辑软件下载安装,pr全系列分享 轻松编辑视频

Adobe Premiere&#xff0c;自其诞生之日起&#xff0c;便以其卓越的性能和出色的表现&#xff0c;稳坐视频编辑领域的王者宝座&#xff0c;赢得了无数专业编辑人员与广大爱好者的青睐。这款强大的视频编辑软件&#xff0c;凭借其丰富的功能和灵活的操作性&#xff0c;为用户提…

(1)Jupyter Notebook 下载及安装

目录 1. Jupyter Notebook是什么&#xff1f;2. Jupyter Notebook特征3. 应用3. 利用Google Colab安装Jupyter Notebook3.1 什么是 Colab&#xff1f;3.2 访问 Google Colab 1. Jupyter Notebook是什么&#xff1f; 百度百科: Jupyter Notebook&#xff08;此前被称为 IPython …

函数创建单链表---无n型,需要 while 循环 + scanf

题目&#xff1a; #include <stdlib.h> struct link{int data;struct link *next; }; struct link* creatLink(); int main(){struct link *head,*p;headcreatLink();for(phead->next ;p;pp->next )printf("%d ",p->data );return 0; }/* 请在这里填…