首页 > 其他分享 >NO35、数组中的逆排序(建议再刷)

NO35、数组中的逆排序(建议再刷)

时间:2023-07-17 11:32:38浏览次数:44  
标签:begin copy end NO35 int 再刷 low1 排序 data


35、数组中的逆排序 很好的题目,建议再刷

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

输入描述:

题目保证输入的数组中没有的相同的数字数据范围:	对于%50的数据,size<=10^4	对于%75的数据,size<=10^5	对于%100的数据,size<=2*10^5

示例1

输入

1,2,3,4,5,6,7,0

输出

7
1、只通过50%的笨方法
int InversePairs(vector<int> data) {
	if (data.size() <= 1) return 0;
	int len = data.size();
	vector<int> dp(len, 0);
	for (int i = len - 2; i >= 0; --i) {

		for (int j = i + 1; j < len; ++j) {
			if (data[i] > data[j]) { 
				//dp[i] = max(dp[i], dp[j] + 1); 
				dp[i]++;
			}

		}
	}

	return  accumulate(dp.begin(), dp.end(), 0) % 1000000007;
        
    }
2、牛客上的一种做法,很厉害

https://www.nowcoder.com/profile/872855282/codeBookDetail?submissionId=78340272

int InversePairs(vector<int> data) {
	if (data.size() == 0)
		return 0;
	vector<int> copy(data);    // 辅助数组,每次递归后有序
	return InversePairsCore(data, copy, 0, data.size() - 1);
}

int InversePairsCore(vector<int>& data, vector<int>& copy, int begin, int end) {
	if (begin == end)
		return 0;
	int mid = begin + (end - begin) /2;
	int left = InversePairsCore(copy, data, begin, mid);//这里的一步很绝啊,减少了交换的这一步
	int right = InversePairsCore(copy, data, mid + 1, end);

	int end1 = mid;     // 比较从尾端开始
	int end2 = end;    // 比较从尾端开始
	int index_copy = end;       // 比较结果存入辅助数组尾端
	long res = 0;

	// 归并排序:相当于两个有序数组合成一个有序表(从尾端开始是为了计数)
	while (begin<= end1 && mid + 1<= end2) {
		if (data[end1] > data[end2]) {
			copy[index_copy--] = data[end1--];
			res += end2 - mid;
			res %= 1000000007;
		}
		else
			copy[index_copy--] = data[end2--];
	}

	while (begin<= end1)
		copy[index_copy--] = data[end1--];
	while (mid + 1<= end2)
		copy[index_copy--] = data[end2--];

	return (left + right + res) % 1000000007;
}

InversePairsCore(copy, data, begin, mid)中 copy和data互换位置好评。。。这样就减少了赋值的那一步了。。。。。

二刷:
1、很棒的一道题目,建议多刷
int InversePairsCore(vector<int>& data, vector<int>& copy, int begin, int end) {
	if (begin == end)
		return 0;
	int mid = begin + (end - begin) / 2;
	int low1 = begin, high1 = mid, low2 = mid + 1, high2 = end;
	int left = InversePairsCore(copy, data, low1, high1);//这里的一步很绝啊,减少了交换的这一步
	int right = InversePairsCore(copy, data, low2, high2);

	long res = 0;
	int copyIndex = low1;
	// 归并排序:相当于两个有序数组合成一个有序表
	while (low1 <= high1 && low2 <= high2) {
		if (data[low1] > data[low2]) {
			copy[copyIndex++] = data[low1++];
			res += high2 - low2 + 1;// data[low1] > data[low2],那么这一次,从a[i]开始到a[mid]必定都是大于这个a[j]的,因为此时分治的两边已经是各自有序了
			res %= 1000000007;
		}
		else
			copy[copyIndex++] = data[low2++];
	}

	while (low1 <= high1)
		copy[copyIndex++] = data[low1++];
	while (low2 <= high2)
		copy[copyIndex++] = data[low2++];

	return (left + right + res) % 1000000007;
}


int InversePairs(vector<int> data) {
	if (data.size() == 0)
		return 0;
	vector<int> copy(data);    // 辅助数组,每次递归后有序
	return InversePairsCore(data, copy, 0, data.size() - 1);
}
2、归并排序,归并成从小到大的序列,这种方法更好理解一些

运行时间:78ms 占用内存:5788k

int InversePairsCore(vector<int>& data, vector<int>& copy, int begin, int end) {
	if (begin == end)
		return 0;
	int mid = begin + (end - begin) / 2;
	int low1 = begin, high1 = mid, low2 = mid + 1, high2 = end;
	int left = InversePairsCore(copy, data, low1, high1);//这里的一步很绝啊,减少了数据交换的这一步
	int right = InversePairsCore(copy, data, low2, high2);

	long res = 0;
	int copyIndex = low1;
	// 归并排序:相当于两个有序数组合成一个有序表
	//下面就开始两两进行比较,若前面的数大于后面的数,就构成逆序对
	while (low1 <= high1 && low2 <= high2) {
		if (data[low1] < data[low2]) {
			
			copy[copyIndex++] = data[low1++];
		}
		else//data[low1] >= data[low2]
		{
			copy[copyIndex++] = data[low2++];
			res += high1 - low1 + 1;
			res %= 1000000007;
		}
			
	}

	while (low1 <= high1)
		copy[copyIndex++] = data[low1++];
	while (low2 <= high2)
		copy[copyIndex++] = data[low2++];


	return (left + right + res) % 1000000007;
}


int InversePairs(vector<int> data) {
	if (data.size() == 0)
		return 0;
	vector<int> copy(data);    // 辅助数组,每次递归后有序
	int res = InversePairsCore(data, copy, 0, data.size() - 1);
	
	//for (int a : data) {
	//	cout << a << " ";
	//}
	//cout << endl;

	//for (int a : copy) {
	//	cout << a << " ";
	//}
	//cout << endl;
	
	return res;

}
力扣上的剑指offer:
剑指 Offer 51. 数组中的逆序对

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

示例 1:

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

限制:

0 <= 数组长度 <= 50000

执行用时:244 ms, 在所有 C++ 提交中击败了97.32%的用户

内存消耗:44.4 MB, 在所有 C++ 提交中击败了100.00%的用户

int reversePairsCore(vector<int>&nums, vector<int>©, int begin, int end){
        if(begin >= end) return 0;//终止条件
        int mid = begin + (end - begin)/2;
        int low1 = begin, high1 = mid, low2 = mid + 1,high2 = end;
        int leftRes = reversePairsCore(copy, nums, low1, high1);
        int rightRes = reversePairsCore(copy, nums, low2, high2);

        int copyIndex = low1,res = 0;
        while(low1 <= high1 && low2 <= high2){
            if(nums[low1] <= nums[low2])//这里需要保持绝对的小
            {
                copy[copyIndex++] = nums[low1++];
            }else{
                res += high1 - low1 + 1;//说明 [low1,high1]此时都是大于 nums[low2]的
                //这里千万注意要 +1 ,因为high1 - low1 就少一个 比如 3-0 = 4,但其实是4个数
                copy[copyIndex++] = nums[low2++];
            }

        }
        while(low1 <= high1)
            copy[copyIndex++] = nums[low1++];

        while(low2 <= high2)
            copy[copyIndex++] = nums[low2++];

        return res + leftRes + rightRes;

    }



    int reversePairs(vector<int>& nums) {
        if( nums.size() <= 1) return 0;
        vector<int> copy(nums);
        return reversePairsCore(nums,copy,0,nums.size()-1);

    }

归并类题目:

力扣 315,327,493

美女帅哥们如果觉得写的还行,有点用的话麻烦点个赞或者留个言支持一下阿秀~
如果觉得狗屁不通,直接留言开喷就完事了。

需要该笔记PDF版本的去个人公众号【拓跋阿秀】下回复“阿秀剑指offer笔记”即可。


标签:begin,copy,end,NO35,int,再刷,low1,排序,data
From: https://blog.51cto.com/u_16015370/6748788

相关文章

  • python利用小列表中元素排序对整个大列表中的小列表进行排序
    一、了解sorted() 函数sorted()函数是Python内置的用于排序可迭代对象的函数,它可以接受多个参数来进行灵活的排序操作。下面是对sorted()函数的参数要求和使用方法的详细说明:参数列表:iterable(必需):表示要进行排序的可迭代对象,例如列表、元组、集合等。key(可选):指定一个函数......
  • vue--day16---列表排序
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metaname="viewport"content="width=device-width,initial-scale=1.0"/><title>watch与computed实现列表过滤</title>......
  • SQLServer 查询语句指定排序规则(查询时区分大小写)
    SQLServer查询语句指定排序规则(查询时区分大小写)介绍可以使用COLLATE子句将字符表达式应用于某个排序规则。为字符文本和变量分配当前数据库的默认排序规则。为列引用分配列的定义排序规则。COLLATE定义数据库或表列的排序规则,或应用于字符串表达式时的排序规则强制转换......
  • 【Oracle】在PL/SQL中使用sql实现插入排序
    【Oracle】在PL/SQL中使用sql实现插入排序一般来说,SQL要排序的话直接使用orderby即可不一般来说,就是瞎搞,正好也可以巩固自己的数据结构基础,主要也发现没有人用SQL去实现这些算法(小声bb)使用SQL实现排序系列:使用SQL实现冒泡排序使用SQL实现选择排序以下是正文:规范:createor......
  • mysql修改所有表的编码排序规则
    #查询数据库各表的排序规则SELECTTABLE_NAME,TABLE_COLLATIONFROMINFORMATION_SCHEMA.TABLESWHERETABLE_SCHEMA='database'; #查询要修改排序规则表的SQL语句SELECTconcat('ALTERTABLE',TABLE_NAME,'CONVERTTOCHARACTERSETutf8mb4COLLATEutf8mb4_unicod......
  • LeetCode 354. Russian Doll Envelopes 排序+LIS
    Youaregivena2Darrayofintegersenvelopeswhereenvelopes[i]=[wi,hi]representsthewidthandtheheightofanenvelope.Oneenvelopecanfitintoanotherifandonlyifboththewidthandheightofoneenvelopearegreaterthantheotherenvelope......
  • Java字符串按字符排序的方法
     Java字符串按字符排序的方法字符串排序是一种常见的编程需求,它可以让我们按照一定的规则对字符串进行比较和排列。在Java中,有多种方法可以实现字符串按字符排序,本文将介绍四种常用的方法,并给出相应的示例代码。1.使用String类的compareTo()方法String类提供了一个compareTo......
  • HJ26 字符串排序
    1.题目读题HJ26 字符串排序   考查点 2.解法思路 代码逻辑 具体实现 publicclassHJ026{publicstaticvoidmain(String[]args){Scannersc=newScanner(System.in);System.out.println(sort(sc.nextLine()));}publ......
  • js实现多列排序
    js实现多列排序根据业务逻辑调整sortData的数据。排序的规则是按照第一列排序,第一列相同按照第二列排序,依次类推//要排序的数据constarray=[{name:'甲'asd,age:10,money:100},{name:'亿',age:10,money:90},{name:'丙',age:9,money:100}]//......
  • java根据实体类排序
    Java根据实体类排序在Java开发中,我们经常需要对实体类进行排序。排序是一种常见的操作,它能够帮助我们对一组对象按照特定的规则进行排列。本文将介绍如何使用Java对实体类进行排序,并提供代码示例来帮助读者更好地理解。实体类排序概述首先,我们需要了解实体类排序的基本概念。排......