逆序对的三种解法

设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。

如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对。

逆序对的解法

第一种:冒泡法(暴力)/ 枚举

直接对原序列进行冒泡排序,统计交换次数,得到的交换次数=逆序对数。

注:求相邻元素的交换次数等价于求序列的逆序对数

第二种:归并排序

对原序列进行归并排序,在每次合并两数组时可以直接统计逆序对的个数。针对左有序序列中的第i号元素,和右有序序列中的第j号元素,若存在 a[j] < a[i] ,则a[i]后的所有

元素都大于a[j]。这种情况下 逆序对的个数result = mid - i + 1

第三种:离散化 + 树状数组

先利用离散化,一次性读入所有数据,然后记录读入数据的下标和值,按照值的大小对值和下标进行排序。得到新的数据后,建立以新的值(排序的序号)为下标的树状数组,树状数组的值为当前状态下该位值出现的次数。在每次向树状数组插入元素时,都利用树状数组查询比当前插入元素的值更大的元素出现的个数。

原文地址:https://www.cnblogs.com/lxqiaoyixuan/p/9742762.html

时间: 2024-10-09 20:47:00

逆序对的三种解法的相关文章

统计逆序对的两种解法

统计逆序对的两种解法 归并排序(mergeSort) 逆序对定义 \(i<j\) 但\(a[i]>a[j]\),假设我们分别使得通过mergeSort使得左右半边有序 即\(a[1]...a[mid]\) 递增, \(a[mid+1]....a[n]\)递增,我们需要通过merge操作,完成整个的排序和新增逆序对的计数,较小值出现在左半边记为 a[i],出现在右半边即为 a[j],那么每次出现在右半边,意味左半边比a[i]大的数都比a[j]大,由此可以统计逆序对 HDU1394 代码实现 #i

UVALive 6257 Chemist&#39;s vows --一道题的三种解法(模拟,DFS,DP)

题意:给一个元素周期表的元素符号(114种),再给一个串,问这个串能否有这些元素符号组成(全为小写). 解法1:动态规划 定义:dp[i]表示到 i 这个字符为止,能否有元素周期表里的符号构成. 则有转移方程:dp[i] = (dp[i-1]&&f(i-1,1)) || (dp[i-2]&&f(i-2,2))     f(i,k):表示从i开始填入k个字符,这k个字符在不在元素周期表中.  dp[0] = 1 代码: //109ms 0KB #include <ios

逆序对 【线段树解法】

逆序对 [线段树解法] 求逆序对问题是一个十分经典的算法问题,通常使用归并排序解决,经gster大神指点,写出了逆序对线段树写法,顺便练了练线段树. 题目传送门:http://noi.openjudge.cn/ch0204/7622/ 代码: 1 /* 2 Segment_Tree 3 author: SHHHS 4 2016-09-28 12:35:17 5 */ 6 #include "bits/stdc++.h" 7 8 using namespace std ; 9 typed

*HDU 1394 经典逆序数的四种解法

1.暴力 [代码]: 1 /*HDU1394暴力写法*/ 2 #include <iostream> 3 #include <string.h> 4 #include <stdio.h> 5 6 using namespace std; 7 8 int A[50005]; 9 int Low[50005],Up[50005]; 10 int main(){ 11 int n; 12 while(~scanf("%d",&n)){ 13 int

最长单调递增子序列的三种解法

问题描述: 找出由n个数组成的序列的最长单调递增子序列 解法一:转化成LCS问题求解,时间复杂度为O(n*n). 思路:原序列为A,把A按升序排序得到序列B,求出A,B序列的最长公共子序列,即为A的最长单调递增子序列. #include<iostream> #include<algorithm> #include<string> #include<cstdio> using namespace std; //转化成LCS问题,时间复杂度O(n*n) int

C语言--求字符串长度的三种解法

问题: 求一个字符串的三种解法 一.计数的方法 #include<stdio.h> #include<assert.h> int my_strlen( char* str) { int count=0; while (*str) { count++; str++; } return count; } int main(void) { char *arr = "abcef"; int ret = my_strlen(arr); printf("%d\n&

LeetCode算法题-First Bad Version(Java实现-三种解法)

这是悦乐书的第200次更新,第210篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第66题(顺位题号是278).您是产品经理,目前领导团队开发新产品.不幸的是,您产品的最新版本未通过质量检查.由于每个版本都是基于以前的版本开发的,因此坏版本之后的所有版本也是坏的. 假设您有n个版本[1,2,...,n]并且您想找出第一个坏的版本,这会导致以下所有版本都不好.您将获得一个API bool isBadVersion(版本),它将返回版本是否错误. 实现一个函数来查找第一

LeetCode算法题-Move Zeroes(Java实现-三种解法)

这是悦乐书的第201次更新,第211篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第67题(顺位题号是283).给定一个数组nums,写一个函数将所有0移动到它的末尾,同时保持非零元素的相对顺序.例如: 输入:[0,1,0,3,12] 输出:[1,3,12,0,0] 注意: 您必须在不制作数组副本的情况下就地执行此操作. 最小化操作总数. 本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试. 02

[LeetCode] Remove Element (三种解法)

Given an array and a value, remove all instances of that value in place and return the new length. The order of elements can be changed. It doesn't matter what you leave beyond the new length. 这题做下来感觉技巧性比较强,解出第一种解法以后我又尝试了另外两种解法,一个比一个简单...我一开始却折腾出了最晦涩