数组的小和&逆序对—归并排序(c++)

数组的小和—归并排序

数组小和

数组小和的定义如下:
例如,数组s = [1, 3, 5, 2, 4, 6],在s[0]的左边小于或等于s[0]的数的和为0;在s[1]的左边小于或等于s[1]的数的和为1;在s[2]的左边小于或等于s[2]的数的和为1+3=4;在s[3]的左边小于或等于s[3]的数的和为1;
在s[4]的左边小于或等于s[4]的数的和为1+3+2=6;在s[5]的左边小于或等于s[5]的数的和为1+3+5+2+4=15。所以s的小和为0+1+4+1+6+15=27
给定一个数组s,实现函数返回s的小和
[要求]
时间复杂度为 O ( n l o g n ) O(nlog_n) O(nlogn),空间复杂度为 O ( n ) O(n) O(n)

#include <iostream>
#include <vector>
using namespace std;
long mergesort(vector<int>& a, int L, int q, int R)
{
	int n = R - L + 1;
	vector<int> b(n, 0);
	int z = 0;
	int left = L;
	int right = q + 1;
	long sum = 0;
	while (left <= q && right <= R)
	{
		sum += (a[left] <= a[right]) ? (R - right + 1)*a[left] : 0;
		b[z++] = (a[left] <= a[right]) ? a[left++] : a[right++];
	}
	while (left <= q)
		b[z++] = a[left++];
	while (right <= R)
		b[z++] = a[right++];
	for (int m = 0; m < n; m++)
		a[L + m] = b[m];
	return sum;
}

long sort(vector<int>& a, int L, int R)
{
	if (L == R)
		return 0;
	int q = L + ((R - L) >> 1);
	return sort(a, L, q) + sort(a, q + 1, R) + mergesort(a, L, q, R);
}
int main()
{
	int N;
	cin >> N;
	vector<int> arr(N, 0);
	for (int i = 0; i < N; i++)
		cin >> arr[i];
	cout << sort(arr, 0, arr.size() - 1);
	system("pause");
	return 0;
}

运行结果
在这里插入图片描述

逆序对

数据范围小的题目
有一组数,对于其中任意两个数组,若前面一个大于后面一个数字,则这两个数字组成一个逆序对。请设计一个高效的算法,计算给定数组中的逆序对个数。

给定一个int数组A和它的大小n,请返回A中的逆序对个数。保证n小于等于5000。

测试样例:
[1,2,3,4,5,6,7,0],8
返回:7

暴力解法

class AntiOrder {
public:
    int count(vector<int> A, int n) {
        // write code here
        int count = 0;
        for (int i = 0; i< n-1;i++)
            for (int j =i+1;j<n;j++)
                if (A[i]>A[j])
                    count++;
        return count;      
    }
};

归并解法

#include <iostream>
#include <vector>
using namespace std;
long mergesort(vector<int>& a, int L, int q, int R)
{
	int n = R - L + 1;
	vector<int> b(n, 0);
	int z = 0;
	int left = L;
	int right = q + 1;
	long sum = 0;
	while (left <= q && right <= R)
	{
		sum += (a[left] > a[right]) ? (q - L + 1) : 0;
		b[z++] = (a[left] <= a[right]) ? a[left++] : a[right++];
	}
	while (left <= q)
		b[z++] = a[left++];
	while (right <= R)
		b[z++] = a[right++];
	for (int m = 0; m < n; m++)
		a[L + m] = b[m];
	return sum;
}

long sort(vector<int>& a, int L, int R)
{
	if (L == R)
		return 0;
	int q = L + ((R - L) >> 1);
	return sort(a, L, q) + sort(a, q + 1, R) + mergesort(a, L, q, R);
}
int main()
{
	int N;
	cin >> N;
	vector<int> arr(N, 0);
	for (int i = 0; i < N; i++)
		cin >> arr[i];
	cout << sort(arr, 0, arr.size() - 1);
	system("pause");
	return 0;
}

数据范围大的题目

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

class Solution {
public:
    typedef long long ll;
    ll mergesort(vector<int>& a, int L, int q, int R)
    {
        int n = R - L + 1;
        vector<int> b(n, 0);
        int z = 0;
        int left = L;
        int right = q + 1;
        ll sum = 0;
        while (left <= q && right <= R)
        {
            sum  += (a[left] > a[right]) ? (q - left + 1) : 0;
            b[z++] = (a[left] <= a[right]) ? a[left++] : a[right++];
        }
        while (left <= q)
            b[z++] = a[left++];
        while (right <= R)
            b[z++] = a[right++];
        for (int m = 0; m < n; m++)
            a[L + m] = b[m];
        return sum;
    }
    ll sort(vector<int>& a, int L, int R)
    {
        if (L == R)
            return 0;
        int q = L + ((R - L) >> 1);
        return sort(a, L, q) + sort(a, q + 1, R) + mergesort(a, L, q, R);
    }
    int InversePairs(vector<int> data) 
    {
        if (data.empty()) return 0;
        long long res = sort(data,0, data.size() - 1);
        return res%1000000007;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值