【C语言算法】求逆序对数目(C语言+归并排序)

题目描述

Background Raymond Babbitt drives his brother Charlie mad. Recently Raymond counted 246 toothpicks spilled all over the floor in an instant just by glancing at them. And he can even count Poker cards. Charlie would love to be able to do cool things like that, too. He wants to beat his brother in a similar task.

Problem Here’s what Charlie thinks of. Imagine you get a sequence of N numbers. The goal is to move the numbers around so that at the end the sequence is ordered. The only operation allowed is to swap two adjacent numbers. Let us try an example: Start with: 2 8 0 3 swap (2 8) 8 2 0 3 swap (2 0) 8 0 2 3 swap (2 3) 8 0 3 2 swap (8 0) 0 8 3 2 swap (8 3) 0 3 8 2 swap (8 2) 0 3 2 8 swap (3 2) 0 2 3 8 swap (3 8) 0 2 8 3 swap (8 3) 0 2 3 8

So the sequence (2 8 0 3) can be sorted with nine swaps of adjacent numbers. However, it is even possible to sort it with three such swaps: Start with: 2 8 0 3 swap (8 0) 2 0 8 3 swap (2 0) 0 2 8 3 swap (8 3) 0 2 3 8

The question is: What is the minimum number of swaps of adjacent numbers to sort a given sequence?Since Charlie does not have Raymond’s mental capabilities, he decides to cheat. Here is where you come into play. He asks you to write a computer program for him that answers the question in O(nlogn). Rest assured he will pay a very good prize for it.

翻译:

背景Raymond Babbitt把他的兄弟Charlie逼疯了。最近,Raymond只看了一眼,就数出246根牙签瞬间洒了一地。他甚至会数扑克。查理也很想做那种很酷的事情。他想在类似的任务中打败他的兄弟。


问题这是查理的想法。想象一下,你得到一个N个数字的序列。目标是移动数字,以便在最后对序列进行排序。唯一允许的操作是交换两个相邻的数字。

让我们尝试一个示例:

从以下内容开始:
2 8 0 3交换(2 8)
8 2 0 3交换(2 0)
8 0 2 3交换(2 3)
8 0 3 2交换(8 0)
0 8 3 2交换(8 3)
0 3 8 2交换(8 2)
0 3 2 8交换(3 2)
0 2 3 8交换(3 8)
0 2 8 3交换(8 3)
0 2 3 8


因此,序列(2 8 0 3)可以通过九个相邻数字的交换进行排序。但是,甚至可以用三种这样的交换对其进行排序:

从:

2 8 0 3交换(8 0)

2 0 8 3交换(2 0)

0 2 8 3互换(8 3)

0 2 3 8

开始


问题是:

对给定序列进行排序时,相邻数字的最小交换次数是多少?由于查理没有雷蒙德的智力,他决定作弊。这就是你发挥作用的地方。他让你为他写一个计算机程序,回答O(nlogn)中的问题。请放心,他会为此支付很高的奖金。

大概意思:

 求相邻数之间最少的交换次数。交换之后是符合递增顺序的(小->大)

输入格式

The first line contains the length N (1 <= N <= 1000) of the sequence; The second line contains the N elements of the sequence (each element is an integer in [-1000000, 1000000]). All numbers in this line are separated by single blanks.

翻译:

第一行包含序列的长度N(1<=N<=1000)第二行包含序列的N个元素(每个元素都是[-1000000,1000000]中的整数)。这一行中的所有数字都用一个空格隔开。

输出格式

Print a single line containing the minimal number of swaps of adjacent numbers that are necessary to sort the given sequence.

翻译:

打印一行,其中包含对给定序列进行排序所需的相邻数字的最小交换次数。

输入样例复制

在这里给出一组输入。例如:

6
-42 23 6 28 -100 65537

输出样例复制

在这里给出相应的输出。例如:

5

 代码示例:

#include <stdio.h>
#include <string.h>
int sum=0;
void merge(int arr[],int L,int M,int R)//治
{//从中间对半分开,求左右数组长度和数组int L_size=M-L;int R_size=R-M+1;int left[L_size];int right[R_size];for(int i=L;i<M;i++){left[i-L]=arr[i];}for(int i=M;i<=R;i++){right[i-M]=arr[i];}//左右数组将小的先放进原先数组,以此类推int i = 0,j = 0,k = L;while(i<L_size&&j<R_size){if(left[i]<right[j]){arr[k]=left[i];i++;k++;}else{arr[k]=right[j];j++;k++;//在这里,我们增加sum,因为left数组中的元素比right数组中的元素大,//符合逆序对定义(左边的数比右边的数大)sum += L_size - i;}}//未进行比较的(当一个数组的元素全部已放入,就无需比剩下一个数组的元素了,因为数组原先已经排好顺序)直接放入while(i<L_size){arr[k]=left[i];i++;k++;}while(j<R_size){arr[k]=right[j];j++;k++;}
}void mergesort(int arr[],int L,int R)//归并排序,分
{if(L==R){return;}else{int M=(L+R)/2+1;mergesort(arr,L,M-1);mergesort(arr,M,R);merge(arr,L,M,R);}
}
int main()
{int n;scanf("%d",&n);int arr[10000]={0};for(int i=0;i<n;i++){scanf("%d",&arr[i]);}int L=0;mergesort(arr,L,n-1);printf("%d",sum);return 0;
}

问题拓展解释:

为什么sum的值为sum += L_size - i;?

答:

在归并排序中计算逆序对时,当我们从right数组取出一个元素并放入到arr数组的当前位置k时,说明left数组中从当前位置i到末尾的所有元素都比这个从right数组取出的元素大。因此,这些left数组中的元素与刚放入的right数组中的元素都会形成逆序对。
 

具体来说,对于left数组中当前位置i之后的每一个元素,它与right数组中当前已放入arr数组的元素都形成了一个逆序对。因为right数组中的这个元素在合并后的arr数组中的位置比left数组中这些元素的位置要靠前,而它们的值又比left数组中的这些元素小。

假设left数组的大小是L_size,当前已经处理了i个元素(即left数组中前i个元素已经正确地放入了arr数组),那么left数组中还未处理的元素数量就是L_size - i。这些元素都将与刚刚从right数组取出的元素形成逆序对。

因此,每当我们从right数组取出一个元素并放入arr数组时,我们就需要增加sum的值,增加的数量正好是left数组中还未处理的元素数量,即L_size - i

NO.45

有问题敬请斧正!感谢您的支持。

<C语言算法> 

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

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

相关文章

代码随想录Day31

Day 31 贪心算法 Part01 今日任务 455.分发饼干 摆动序列 最大子序和 代码实现 455.分发饼干 //自己想的&#xff0c;虽然看着不让代码随想录给出的解法简洁&#xff0c;但是理论是一样的public int findContentChildren(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(…

Git浅谈配置文件和免密登录

一、文章内容 简述git三种配置ssh免密登录以及遇见的问题git可忽略文件git remote 相关操作 二、Git三种配置 项目配置文件(局部)&#xff1a;项目路径/.git/config 文件 git config --local user.name name git config --local user.email 123qq.cc全局配置文(所有用户): …

【Web】记录CISCN 2021 总决赛 ezj4va题目复现——AspectJWeaver

目录 前言 原理分析 step 0 step 1 EXP 前文&#xff1a;【Web】浅聊Java反序列化之AspectJWeaver——任意文件写入-CSDN博客 前言 这就是当年传说中的零解题嘛&#x1f62d;&#xff0c;快做&#x1f92e;了 有了之前的经验&#xff0c;思路顺挺快的&#xff0c;中间不…

网络基础(一)初识

1、计算机网络背景 1.1、网络发展 1. 独立模式: 计算机之间相互独立&#xff1b; 2. 网络互联: 多台计算机连接在一起&#xff0c;完成数据共享&#xff1b; 3. 局域网LAN: 计算机数量更多了, 通过交换机和路由器连接在一起; 4. 广域网WAN: 将远隔千里的计算机都连在一起;…

突破编程_C++_STL教程( priority_queue 的基础知识)

1 std::priority_queue 概述 std::priority_queue 是 C 标准库中的一个容器适配器&#xff0c;它提供了一种实现优先队列数据结构的机制。优先队列是一种特殊的队列&#xff0c;其中元素的出队顺序不是基于它们进入队列的顺序&#xff0c;而是基于它们的优先级。优先级最高的元…

【python】python汽车效能数据集—回归建模(源码+数据集)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

yaml 语法和在线解析工具

文章目录 在线解析工具1. 简介2. 语法规则3. 数据类型3.1 数组&#xff1a;3.2对象&#xff1a;3.3 标量3.4 复合结构3.5 锚点3.5.1 单个锚点3.5.6 多个锚点 3.6 引号 参考 在线解析工具 工具1 工具2 1. 简介 Yaml是一种可读性高的数据标记语言&#xff0c;Yaml文件是一种配…

使用VisualStudio集成开发nodejs的addon项目

文章目录 Visual Studio中的nodeJS项目配置Visual Studio中的addon项目配置一般的addon项目手写CPP文件 & VS构建.node文件的本质分析使用VS来创建node文件项目另外一个验证方式Visual Studio中的nodeJS项目配置 在VisualStudio的IDE中,已经可以创建一些基本的nodejs项目…

vscode配置C语言打断点

搞了半天&#xff0c;也不知道为什么&#xff0c;不能打断点&#xff0c;后来就可以了。 1&#xff0c;VSCODE启动要管理员启动。 launch.json文件内容 { "version": "0.2.0", "configurations": [ { "name": "(Windows) Laun…

Python从入门到精通秘籍十五

一、Python之基础地图的使用 当涉及到地图数据和地理信息处理时&#xff0c;Python中最常用的库是Folium&#xff0c;它是一个基于Leaflet.js的Python库&#xff0c;可以轻松创建交互式地图可视化。 首先&#xff0c;你需要安装Folium库。可以通过以下命令使用pip进行安装&am…

45.i++和++i

目录 一.基本概念 二.区别 三.总结 四.视频教程 一.基本概念 i和i两者的作用都是自增加1。单独使用的话&#xff0c;i和i&#xff0c;效果都是一样的&#xff0c;就是ii1。 int main() {int i 0;i; } int main() {int i 0;i; } 最后的结果都是1。 二.区别 如上单独使…

SpringBoot—@ConditionalOnBean与@ConditionalOnClass

一、ConditionalOnBean概念 需求场景 比如下面一种场景&#xff0c;我在实例化People对象的时候&#xff0c;需要注入一个City对象。这个时候问题来了&#xff0c;如果city没有实例化&#xff0c;那么下面就会报空指针或者直接报错。 所以这里需求很简单&#xff0c;就是当前c…

就业班 第二阶段 2401--3.19 day4 主从复制

一、MySQL-Replication&#xff08;主从复制&#xff09; 1.1、MySQL Replication 主从复制&#xff08;也称 AB 复制&#xff09;允许将来自一个MySQL数据库服务器&#xff08;主服务器&#xff09;的数据复制到一个或多个MySQL数据库服务器&#xff08;从服务器&#xff09;…

MySQL面试题--最全面-索引

目录 一、索引 1.MySQL是如何让实现的索引机制&#xff1f; 2.InnoDB索引与MyISAM索引实现的区别是什么&#xff1f; 3.一个表中如果没有创建索引&#xff0c;那么还会创建B树吗&#xff1f; 4.说一下B树索引实现原理&#xff08;数据结构&#xff09; 5.聚簇索引与非聚簇…

Handler的post与sendMessage的区别和应用场景

Handler的post与sendMessage的区别和应用场景 区别在于post实现起来比较简单。而sendMessage()则需要自己重写handleMessage&#xff08;&#xff09;方法。 两者在本质上都没有什么区别。post方法适合单一的场景&#xff0c;实现起来比较方便。sendMessage()适合需要作条件判…

弱电工程包括哪些工程?

​一、弱电工程的分部有哪些? 分为基础、主体、装饰工程、强电、弱电、消防、暖通、给排水工程&#xff0c;桩基、筏板、模板、钢筋、混凝土、砌体、粉刷、地坪等 二、弱电工程系统包括哪些? 弱电系统包括&#xff1a;闭路电视监控系统、防盗报警系统、门禁系统、电子巡更…

[小程序开发] 分包加载

一、介绍 分包加载是一种小程序的优化技术&#xff0c;将小程序不同功能的代码&#xff0c;分别打包成不同的子包&#xff0c;在构建时打包成不同的分包&#xff0c;用户在使用时按需进行加载&#xff0c;在构建小程序分包项目时&#xff0c;构建会输出一个或多个分包&#xff…

突破编程_C++_C++11新特性(type_traits的复合类型特性以及关系类型特性)

1 type_traits 复合类型特性 1.1 std::is_function std::is_function 是一个模板类&#xff0c;用于检查一个类型是否为函数类型。 定义&#xff1a; template< class T > struct is_function;当 T 为函数类型则为 true&#xff0c;否则为 false。 样例&#xff1…

专业前沿问题问答合集10-2——比特币的加密原理

专业前沿问题问答合集10-2——比特币的加密原理 比特币的加密原理 比特币作为一种加密货币,其安全性和功能性主要基于密码学原理和区块链技术。以下是比特币加密原理的关键组成部分: 1. 非对称加密(公钥和私钥) 比特币使用非对称加密技术来确保交易的安全性。每个比特币…

Docker 浅谈重要的概念和应用场景

文章目录 一、重要的概念二、特性三、特性的常见应用场景四、基本使用流程 一、重要的概念 镜像&#xff08;Image&#xff09;&#xff1a;镜像是Docker的基本构建块&#xff0c;它是一个只读的文件&#xff0c;包含了运行应用程序所需的所有文件系统、库和依赖项。可以将镜像…