【剑指】51.数组中的逆序对

题目描述

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

算法分析

  • 先把数组分割成子数组,先统计出子数组内部的逆序对的数目,然后再统计出两个相邻子数组之间的逆序对的数目。在统计逆序对的过程中,还需要对数组进行排序。如果对排序算法很熟悉,我们不难发现这个过程实际上就是归并排序

提交代码(递归方法):

class Solution {
public:
	int InversePairs(vector<int> data) {
		if (data.empty())
			return 0;
		vector<int> temp(data.size());
		
		return MSort(data, temp, 0, data.size() - 1);
	}

	int MSort(vector<int> &data, vector<int> &temp, int start, int end)
	{
		int left = 0, right = 0, count = 0;
		if (start == end)
		{
			temp[start] = data[start];
		}
		else
		{
			int middle = (start + end) / 2;
			left = MSort(data, temp, start, middle);
			right = MSort(data, temp, middle + 1, end);
			count = Merge(data, temp, start, middle, end);
		}
		return (left + right + count) % 1000000007;

	}

	int Merge(vector<int> &data, vector<int> &temp, int start, int middle, int end)
	{
		int i = middle, j = end;
		int index = end;
		int count = 0;
		// 主循环,把数据合并
		while (i >= start && j >= middle + 1)
		{
			if (data[i] > data[j])
			{
				count += (j - middle);
				temp[index--] = data[i--];
				if (count >= 1000000007)//数值过大求余
					count %= 1000000007;
			}
			else
				temp[index--] = data[j--];
		}

		// 如果是因为后边子列的数据全部放在临时向量中导致主循环结束
		// 则把前面没放完的数据依次放入临时变量中
		while (i >= start)
			temp[index--] = data[i--];

		// 同上处理前面子列数据全部先放入向量中的情况
		while (j >= middle + 1)
			temp[index--] = data[j--];

		// 注意!不能直接用a=tmpArray,因为可能只是复制子列
		for (int i = start; i <= end; ++i)
			data[i] = temp[i];

		return count;
	}
};

提交代码(非递归方法):

class Solution {
public:
	int InversePairs(vector<int> data) {
		if (data.empty())
			return 0;

		return MSort(data);
	}

	int MSort(vector<int> &data)
	{
		int count = 0;
		int k = 1;
		vector<int> temp(data.size());
		while (k < data.size())
		{
			count += MergePass(data, temp, k);
			if (count >= 1000000007)//数值过大求余
				count %= 1000000007;
			k *= 2;
		}
		return count;

	}

	int MergePass(vector<int> &data, vector<int> &temp, int k)
	{
		int i = 0, count = 0;
		int n = data.size();

		while (i < (n - 2 * k + 1))
		{
			count += Merge(data, temp, i, i + k - 1, i + 2 * k - 1);
			i += 2 * k;
			if (count >= 1000000007)//数值过大求余
				count %= 1000000007;
		}

		if (i < n - k + 1)
		{
			count += Merge(data, temp, i, i + k - 1, n - 1);
			if (count >= 1000000007)//数值过大求余
				count %= 1000000007;
		}

		return count % 1000000007;
	}

	int Merge(vector<int> &data, vector<int> &temp, int start, int middle, int end)
	{
		int i = middle, j = end;
		int index = end;
		int count = 0;
		// 主循环,把数据合并
		while (i >= start && j >= middle + 1)
		{
			if (data[i] > data[j])
			{
				count += (j - middle);
				temp[index--] = data[i--];
				if (count >= 1000000007)//数值过大求余
					count %= 1000000007;
			}
			else
				temp[index--] = data[j--];
		}

		// 如果是因为后边子列的数据全部放在临时向量中导致主循环结束
		// 则把前面没放完的数据依次放入临时变量中
		while (i >= start)
			temp[index--] = data[i--];

		// 同上处理前面子列数据全部先放入向量中的情况
		while (j >= middle + 1)
			temp[index--] = data[j--];

		// 注意!不能直接用a=tmpArray,因为可能只是复制子列
		for (int i = start; i <= end; ++i)
			data[i] = temp[i];

		return count;
	}
};

测试代码:

// ====================测试代码====================
void Test(char* testName, vector<int> data, int expected)
{
	if (testName != nullptr)
		printf("%s begins: ", testName);

	Solution s;
	if (s.InversePairs(data) == expected)
		printf("Passed.\n");
	else
		printf("Failed.\n");
}

void Test1()
{
	vector<int> data = { 1, 2, 3, 4, 7, 6, 5 };
	int expected = 3;

	Test("Test1", data, expected);
}

// 递减排序数组
void Test2()
{
	vector<int> data = { 6, 5, 4, 3, 2, 1 };
	int expected = 15;

	Test("Test2", data, expected);
}

// 递增排序数组
void Test3()
{
	vector<int> data = { 1, 2, 3, 4, 5, 6 };
	int expected = 0;

	Test("Test3", data, expected);
}

// 数组中只有一个数字
void Test4()
{
	vector<int> data = { 1 };
	int expected = 0;

	Test("Test4", data, expected);
}


// 数组中只有两个数字,递增排序
void Test5()
{
	vector<int> data = { 1, 2 };
	int expected = 0;

	Test("Test5", data, expected);
}

// 数组中只有两个数字,递减排序
void Test6()
{
	vector<int> data = { 2, 1 };
	int expected = 1;

	Test("Test6", data, expected);
}

// 数组中有相等的数字
void Test7()
{
	vector<int> data = { 1, 2, 1, 2, 1 };
	int expected = 3;

	Test("Test7", data, expected);
}

void Test8()
{
	int expected = 0;

	Test("Test8", vector<int>(), expected);
}

int main(int argc, char* argv[])
{
	Test1();
	Test2();
	Test3();
	Test4();
	Test5();
	Test6();
	Test7();
	Test8();

	return 0;
}

猜你喜欢

转载自blog.csdn.net/ansizhong9191/article/details/81033232