Count of Smaller Numbers After Self

    题目来源leetcode 315
    给定一个乱序的数字序列A,生成一个序列B。B[i]表示A[i+1]到A的最后一项中比A[i]小的数字的个数。
    如果用简单的扫描,需要O(n^2)的复杂度,我们寻求更好的办法。
    设原序列为A,所求序列为B,所有元素初始化为0。构造一个结构体,保存了A中每个元素的值和下标,设置结构体序列C,对C进行按元素的值从大到小的归并排序。在归并两个已经

排好序的序列X和Y的过程中,如果在比较X与Y两个头元素P、Q的值大小的过程中,出现了P>Q的情况,那么就说明P元素比Q元素及其在Y序列中后面的元素都要大。通过P元素封装的下标,可以找到其应该对应B序列中的哪个位置,这样就可以更新B序列。每一次归并的更新都不会重复计算或漏计,当归并排序完成之后,B序列就更新完毕了。复杂度和归并排序相同,为O(nlogn)。


struct num
{
	int v;
	int index;
	num()
	{

	}
	num(int x, int y)
	{
		v = x;
		index = y;
	}
};
void merge(vector<int>& ans, vector<num>& set, int left1, int right1, int left2, int right2)//稍作修改的归并过程
{
	int i = left1, j = left2;
	vector<num> temp;
	while (1)
	{
		if (i > right1&&j > right2)
		{
			break;
		}
		if (i > right1)
		{
			temp.push_back(set[j]);
			j++;
		}
		else
		{
			if (j > right2)
			{
				temp.push_back(set[i]);
				i++;
			}
			else
			{
				if (set[i].v > set[j].v)
				{
					temp.push_back(set[i]);
					ans[set[i].index]+=(right2-j+1);//更新最终的答案序列
					i++;
				}
				else
				{
					temp.push_back(set[j]);
					j++;
				}
			}
		}
	}
	for (int i = left1; i <=right2; i++)
	{
		set[i] = temp[i-left1];
	}
}
void mergesort(vector<int>& ans, vector<num>& set, int left, int right)
{
	if (left == right)
		return;
	mergesort(ans, set, left, (left+right)/2);
	mergesort(ans, set, (left + right) / 2+1, right);
	merge(ans, set, left, (left + right) / 2, (left + right) / 2+1, right);
}
vector<int> countSmaller(vector<int>& nums) {
	vector<num> set(nums.size());
	vector<int> ans(nums.size(), 0);
	if (nums.size() == 0)//讨论原序列为空的情况
		return ans;
	for (int i = 0; i < nums.size(); i++)
	{
		set[i].v = nums[i];
		set[i].index = i;
	}
	mergesort(ans, set, 0, nums.size() - 1);
	return ans;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值