数组小和
数组小和的定义如下:
例如,数组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;
}
};