首页 > 其他分享 >数组中的逆序对

数组中的逆序对

时间:2023-04-18 10:55:24浏览次数:35  
标签:tmp 归并 nums int 数组 排序 逆序

数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

示例 1:

输入: [7,5,6,4]
输出: 5

限制:

0 <= 数组长度 <= 50000

分析:

对于数组[7,5,6,4],若要计算其中的逆序对个数,及 [7,5],[7,6],[7,4],[5,4],[6,4],可以发现,若将所有逆序对依次交换其在数组中的位置,我们将会得到一个有序的数组,因此,我们可以用排序的思想来解决该题。

归并排序:

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

归并排序是建立在归并操作上的一种有效的排序算法,归并排序对序列的元素进行逐层折半分组,然后从最小分组开始比较排序,合并成一个大的分组,逐层进行,最终所有的元素都是有序的

1681785202276

1.时间复杂度 归并排序算法每次将序列折半分组,共需要logn轮,因此归并排序算法的时间复杂度是O(nlogn)

2.空间复杂度 归并排序算法排序过程中需要额外的一个序列去存储排序后的结果,所占空间是n,因此空间复杂度为O(n)

3.稳定性 归并排序算法在排序过程中,相同元素的前后顺序并没有改变,所以归并排序是一种稳定排序算法

因此要求数组中的逆序对数,只需要计算通过归并排序,将数组中逆序对交换的次数即可。代码如下:

#include<iostream>
using namespace std;
int res = 0;
void MergeSort(int a[], int l,int m,int r)//合并分组进行排序
{
int t[10100];//辅助数组
for (int i = l;i <= r;i++)
{
t[i - l] = a[i];
}
int i = l,j = m + 1;
for (int k = l;k <= r;k++)
{
if (i>m&&j<=r)//i越界而j没有越界
{
a[k] = t[j-l];
res+=(j-m);
j++;
}
else if (i<=m&&j>r)//j越界而i没有越界
{
a[k] = t[i-l];
i++;
}
else if (t[i-l]>t[j-l])//i和j进行比较
{
a[k] = t[j - l];
res += (j-m);//计算逆序对
j++;
}
else if (t[i-l]<=t[j-l])//i和j进行比较
{
a[k] = t[i - l];
i++;
}
}
}
void Merge(int a[],int l,int r)//递归进行归并排序
{
if (l >= r)
return;
int m = (l + r) / 2;
Merge(a, l, m);
Merge(a, m+1, r);
MergeSort(a, l, m, r);
}
int main()
{
   int n,a[10100];
cin >> n;
for (int i = 0;i < n;i++)
{
cin>>a[i];
}
Merge(a, 0, n-1);
for (int i = 0;i < n;i++)
{
cout << a[i] << " ";
}
cout <<endl;
cout <<"逆序对个数:"<<res<<endl;
system("pause");
return 0;
}

力扣 剑指 Offer 51. 数组中的逆序对 题解:

class Solution {
public:
   int mergeSort(vector<int>& nums, vector<int>& tmp, int l, int r) {
       if (l >= r) {
           return 0;
      }

       int mid = (l + r) / 2;
       int inv_count = mergeSort(nums, tmp, l, mid) + mergeSort(nums, tmp, mid + 1, r);
       int i = l, j = mid + 1, pos = l;
       while (i <= mid && j <= r) {
           if (nums[i] <= nums[j]) {
               tmp[pos] = nums[i];
               ++i;
               inv_count += (j - (mid + 1));
          }
           else {
               tmp[pos] = nums[j];
               ++j;
          }
           ++pos;
      }
       for (int k = i; k <= mid; ++k) {
           tmp[pos++] = nums[k];
           inv_count += (j - (mid + 1));
      }
       for (int k = j; k <= r; ++k) {
           tmp[pos++] = nums[k];
      }
       copy(tmp.begin() + l, tmp.begin() + r + 1, nums.begin() + l);
       return inv_count;
  }

   int reversePairs(vector<int>& nums) {
       int n = nums.size();
       vector<int> tmp(n);
       return mergeSort(nums, tmp, 0, n - 1);
  }
};
 

标签:tmp,归并,nums,int,数组,排序,逆序
From: https://www.cnblogs.com/Codingemon/p/17328799.html

相关文章

  • Java 实现Arrays 数组工具类
    ClassArrays是java工具包自带的非常强大的数组工具类,今天手工实现了一部分功能,部分参考实现如下publicclassMyArrays{//最大值/***获取int数组最大值**@paramarr:代遍历的数组*@return数组最大值*/publicintgetMax(......
  • 有序数组的平方
    有序数组的平方给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。示例1:输入:nums=[-4,-1,0,3,10]输出:[0,1,9,16,100]解释:平方后,数组变为[16,1,0,9,100]排序后,数组变为[0,1,9,16,100]Python解一:classSolution(object......
  • 长度最小的子数组
    长度最小的子数组给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其和≥target的长度最小的连续子数组[numsl,numsl+1,...,numsr-1,numsr],并返回其长度。如果不存在符合条件的子数组,返回0。示例1:输入:target=7,nums=[2,3,1,2,4,3]......
  • 【LBLD】常数时间删除-查找数组中的任意元素
    常数时间删除-查找数组中的任意元素380.O(1)时间插入、删除和获取随机元素classRandomizedSet{private:vector<int>nums;unordered_map<int,int>num2index;public:RandomizedSet(){srand(time(0));}boolinsert(intval){......
  • 轮换数组——给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数
    示例输入:nums=[1,2,3,4,5,6,7],k=3输出:[5,6,7,1,2,3,4]解释:向右轮转1步:[7,1,2,3,4,5,6]向右轮转2步:[6,7,1,2,3,4,5]向右轮转3步:[5,6,7,1,2,3,4]这里使用reverse函数来解决问题,思路是:1.反转整个字符串2.反转区间为前k的子串3.反转区间为k到末尾的......
  • 定义函数数组
    interfaceFunctionArrayInterface//定义接口,希望批量执行的函数用统一的名称定义在接口内{voidrunit();}classfuncAimplementsFunctionArrayInterface//函数A{publicvoidrunit(){System.out.println("你运行了函数func......
  • 第五章 数组
    5.1数组的概述5.1.1数组的定义数组是相同类型数据的有序集合。数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。其中,每一个数据称为一个数据元素,每一个数据元素可以通过一个下标来访问他们。5.2数组的声明创建5.2.1数组的声明与创建首先必......
  • reduce 构建新对象或者 数组
    //原对象constinfo=[{name:"A",value:4,},{name:"B",value:7,},{name:"C",value:10,}];//期望对象{A:4,B:7,C:10,}//reduce:co......
  • C# 数组深拷贝浅拷贝
    1bool[]tmp1={true,true};2bool[]tmp2;34//tmp2=tmp1;//浅拷贝更改tmp2会影响tmp156tmp2=(bool[])tmp1.Clone();//克隆深拷贝更改tmp2不会影响tmp178tmp2[0]=false;9......
  • 动态规划:剑指 Offer 42. 连续子数组的最大和
    题目描述:输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)。 提示:1<= arr.length<=10^5-100<=arr[i]<=100   classSolution{publicintmaxSubArray(intnums[]){intres......