剑指offer[51]数组中的逆序对

个人觉得这是剑指最难的一题。

分治partition:

 

 归并merge:

// InversePairs.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<vector>
using namespace std;
//遍历的方法,时间复杂度为O(n^2)
class SolutionTraversal {
public:
	int InversePairs(vector<int> data)
	{
		if (data.size() == 0)
		{
			return NULL;
		}
		int sum = 0;
		int judge = 0;
		for (int i = 0; i < data.size() - 1; i++)
		{
			if (data[i] > data[i + 1])
			{
				for (int j = 0; j <= i; j++)
				{
					if (data[j] > data[i + 1])
					{
						sum++;
					}
				}
			}
		}
		return sum % 1000000007;
	}
};


//归并思想,时间复杂度为O(nlogn)
class Solution
{
public:
	int InversePairs(vector<int> data)
	{
		if (data.size() <= 0)//鲁棒性
		{
			return NULL;
		}
		int arr[200000] = {};//题目size最大为200000
		for (int i = 0; i < data.size(); i++)
		{
			arr[i] = data[i];
		}
		int low = 0;
		int high = data.size() - 1;
		long long p = 0;
		partition(arr, low, high, p);//归并排序
		return p % 1000000007;//从这里取模1000000007可以知道p很大,所以需要long long p
	}


	void partition(int arr[], int low, int high, long long& p)
	{
		if (low == high)//分治,递归终止条件
		{
			return;
		}
		else
		{
			int mid = (high + low) / 2;//取中间
			partition(arr, low, mid, p);//左分治
			partition(arr, mid + 1, high, p);//右分治
			merge(arr, low, mid, high, p);//归并,将两个有序序列合并为一个有序序列
		}
	}

	void merge(int arr[], int low, int mid, int high, long long& p)
	{
		vector<int>temp;
		int p1 = low; int p2 = mid + 1;
		while (p1 <= mid && p2 <= high)
		{
			if (arr[p1] <= arr[p2])
			{
				temp.push_back(arr[p1]);
				p1++;
			}
			else
			{
				//对于本题,在两个子序列left、right合并过程中,当left中当前元素A大于right中当前元素B时,
				//因为right序列已经有序,所以不用比较,A一定大于right序列当前所有剩余元素,其全部可以与A组成逆序对,
				//即通过一次比较可到一批逆序对,加速统计过程。
				temp.push_back(arr[p2]);
				// 与归并排序不同的地方,在merge过程中统计逆序对数
				p = p + mid - p1 + 1; //计算p1到mid中的元素个数,即p2的逆序数。因为只有p1到mid中的元素大于p2
				p2++;
			}
		}
		while (p1 <= mid)//只剩左边了
		{
			temp.push_back(arr[p1]);
			p1++;
		}
		while (p2 <= high)//只剩右边了
		{
			temp.push_back(arr[p2]);
			p2++;
		}
		for (int i = 0; i < temp.size(); i++)
		{
			arr[low + i] = temp[i];//按照排好的顺序,从low开始插入,十分注意
		}
	}
};

int main()
{
	Solution s;
	vector<int> data;
	for (int i = 0; i < 100000; i++)
	{
		int num = rand() % 999999;
		data.push_back(num);
	}
	auto result = s.InversePairs(data);
	return 0;
}
发布了23 篇原创文章 · 获赞 0 · 访问量 137

猜你喜欢

转载自blog.csdn.net/qq_35683407/article/details/104322236
今日推荐