leetcode刷题. 面试题51. 数组中的逆序对. 每日打卡

数组逆序对求解
本文介绍了一种利用归并排序算法求解数组中逆序对总数的方法,详细解析了算法实现过程,包括子问题的解决策略,如两个有序数组的逆序对计算,以及如何通过递归和迭代实现整体解决方案。

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

归并排序,时间复杂度o(nlog(n)), 空间复杂度o(n)

class Solution3 {
public:
	int reversePairs(vector<int>& nums) {

		vector<int> tmp(nums.size(), 0);
		return mergeSort(nums, 0, nums.size() - 1, tmp);
	}
private:

	int mergeSort(vector<int>& nums, int lo, int hi, vector<int> &tmp) {
		 
		if (lo >= hi)
			return 0;

		int mid = (lo + hi) / 2;
		int count = mergeSort(nums, lo, mid, tmp) + mergeSort(nums, mid + 1, hi, tmp);

		// 对两个有序数组计算逆序对
		int p1 = mid;
		int p2 = hi;
		while (p1 >= lo && p2 > mid) {

			if (nums[p1] > nums[p2]) {

				count += p2 - mid;
				p1--;
				continue;
			}
			p2--;
		}
		// 对两个有序数组进行排序
		p1 = lo;
		p2 = mid + 1;
		int c = 0;
		while (p1 <= mid && p2 <= hi) {
			if (nums[p1] <= nums[p2]) {
				tmp[c++] = nums[p1++];
				continue;
			}
			tmp[c++] = nums[p2++];
		}

		while (p1 <= mid)
			tmp[c++] = nums[p1++];
		while (p2 <= hi)
			tmp[c++] = nums[p2++];

		// 合并
		for (int i = 0; i <= hi - lo; i++)
			nums[lo + i] = tmp[i];

		return count;
	}
};

这里面抽出了一个子问题,就是:两个有序数组的逆序对?

数组1:[2, 6, 8]
数组2:[1, 3, 5, 7]

则组成的逆序对:
[2, 1]
[6, 1]
[6, 3]
[6, 5]
[8, 1]
[8, 3]
[8, 5]
[8, 7]

时间复杂度o(n + m) 

int reversePair(vector<int>& nums1, vector<int>& nums2) {

	int count = 0;

	int p1 = nums1.size() - 1;
	int p2 = nums2.size() - 1;

	while (p1 >= 0 && p2 >= 0) {

		if (nums1[p1] > nums2[p2]) {
			count += p2 + 1;
			p1--;
			continue;
		}
		p2--;
	}
	return count;
}

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值