归并排序&&数组中逆序对问题

题目:在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。例如在数组{7,5,6,4}中,一共存在5个逆序对,分别是{7,5}、{7,6}、{7,4}、{5,4}、{6,4} 

解析:我们可以利用归并排序的过程中统计出逆序对的个数,算法时间复杂度为O(nlogn)

 

归并排序实现代码:

#include <iostream>
using namespace std;

void Merge(int arr[], int temp_arr[], int begin, int middle, int end)
{
	for(int i = begin; i <= end; i++)// 将arr中元素保存至副本
	{
		temp_arr[i] = arr[i];
	}

	int left = begin;
	int right = middle+1;
	int temp_pos = begin;

	while(left <= middle && right <= end)
	{
		if(temp_arr[left] <= temp_arr[right]) 
		{
			arr[temp_pos++] = temp_arr[left++];
		}
		else 
		{
			arr[temp_pos++] = temp_arr[right++];
		}
	}
	while(left <= middle)
	{
		arr[temp_pos++] = temp_arr[left++];
	}
	while(right <= end)
	{
		arr[temp_pos++] = temp_arr[right++];
	}
}
void MergeSort(int arr[], int temp_arr[], int begin, int end)
{
	if(begin < end) //至少两个元素
	{
		int middle = (begin + end)/2;
		MergeSort(arr, temp_arr, begin, middle);
		MergeSort(arr, temp_arr, middle+1, end);
		Merge(arr, temp_arr, begin, middle,end);
	}
}
void MergeSort(int arr[], int length)
{
	if(NULL == arr || length <= 0)
		return;

	int *temp_arr = new int[length]; // 临时数组,保存arr副本 
	if(NULL == temp_arr)
		return;   //  这里不单单应是直接return就可以了,还要让用户知道错误
	
	MergeSort(arr, temp_arr, 0, length - 1);
	
	delete[] temp_arr;

}
int main()
{
	int a[] = {2, 3, 4, 56, 7, 8, 9, 5, 4};
	MergeSort(a, 9);
	
	for(int i = 0; i != 9; i++)
		cout << a[i] <<endl;
	system("pause");
}

 

数组中逆序对问题实现代码

#include <iostream>
using namespace std;

int reverse_pairs_count = 0;

void Merge(int arr[], int temp_arr[], int begin, int middle, int end)
{
	for(int i = begin; i <= end; i++)// 将arr中元素保存至副本
	{
		temp_arr[i] = arr[i];
	}

	int left = begin;
	int right = middle+1;
	int temp_pos = begin;

	while(left <= middle && right <= end)
	{
		if(temp_arr[left] <= temp_arr[right]) 
		{
			arr[temp_pos++] = temp_arr[left++];
		}
		else 
		{
			//temp_arr[left] > temp_arr[right], 表示出现了逆序对,此时由于
			//temp_arr[left..middle]是已经有序了,那么temp_arr[i+1], temp_arr[i+2], ... temp_arr[middle]都是大于temp[right]的,
			//都可以和temp[right]组成逆序对,因此reverse_pairs_count +=middle - left + 1
			reverse_pairs_count += middle - left + 1;
			arr[temp_pos++] = temp_arr[right++];
		}
	}
	while(left <= middle)
	{
		arr[temp_pos++] = temp_arr[left++];
	}
	while(right <= end)
	{
		arr[temp_pos++] = temp_arr[right++];
	}
}
void MergeSort(int arr[], int temp_arr[], int begin, int end)
{
	if(begin < end) //至少两个元素
	{
		int middle = (begin + end)/2;
		MergeSort(arr, temp_arr, begin, middle);
		MergeSort(arr, temp_arr, middle+1, end);
		Merge(arr, temp_arr, begin, middle,end);
	}
}
void MergeSort(int arr[], int length)
{
	if(NULL == arr || length <= 0)
		return;

	int *temp_arr = new int[length]; // 临时数组,保存arr副本 
	if(NULL == temp_arr)
		return;   //  这里不单单应是直接return就可以了,还要让用户知道错误
	
	MergeSort(arr, temp_arr, 0, length - 1);
	
	delete[] temp_arr;

}


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值