给定大小为A[]
的数组n
,构建两个数组C_min[]
和C_max[]
,以便
C_min[i]
表示小于A[i]
和A[0 to i]
中C_max[i]
的元素数量
A[i]
表示A[i to n-1]
A[5] = {1,2,4,3,6}
的元素数量
例如C_min[]
然后C_max[]
和C_min[5] = {0,1,2,2,4}
将是
C_max[5] = {4,3,1,1,0}
#include <bits/stdc++.h>
int _mergeSort(int arr[], int temp[], int left, int right);
int merge(int arr[], int temp[], int left, int mid, int right);
/* This function sorts the input array and returns the
number of inversions in the array */
int mergeSort(int arr[], int array_size)
{
int *temp = (int *)malloc(sizeof(int)*array_size);
return _mergeSort(arr, temp, 0, array_size - 1);
}
/* An auxiliary recursive function that sorts the input array and
returns the number of inversions in the array. */
int _mergeSort(int arr[], int temp[], int left, int right)
{
int mid, inv_count = 0;
if (right > left)
{
/* Divide the array into two parts and call _mergeSortAndCountInv()
for each of the parts */
mid = (right + left)/2;
/* Inversion count will be sum of inversions in left-part, right-part
and number of inversions in merging */
inv_count = _mergeSort(arr, temp, left, mid);
inv_count += _mergeSort(arr, temp, mid+1, right);
/*Merge the two parts*/
inv_count += merge(arr, temp, left, mid+1, right);
}
return inv_count;
}
/* This funt merges two sorted arrays and returns inversion count in
the arrays.*/
int merge(int arr[], int temp[], int left, int mid, int right)
{
int i, j, k;
int inv_count = 0;
i = left; /* i is index for left subarray*/
j = mid; /* i is index for right subarray*/
k = left; /* i is index for resultant merged subarray*/
while ((i <= mid - 1) && (j <= right))
{
if (arr[i] <= arr[j])
{
temp[k++] = arr[i++];
}
else
{
temp[k++] = arr[j++];
/*this is tricky -- see above explanation/diagram for merge()*/
inv_count = inv_count + (mid - i);
}
}
/* Copy the remaining elements of left subarray
(if there are any) to temp*/
while (i <= mid - 1)
temp[k++] = arr[i++];
/* Copy the remaining elements of right subarray
(if there are any) to temp*/
while (j <= right)
temp[k++] = arr[j++];
/*Copy back the merged elements to original array*/
for (i=left; i <= right; i++)
arr[i] = temp[i];
return inv_count;
}
/* Driver progra to test above functions */
int main(int argv, char** args)
{
int arr[] = {1, 20, 6, 4, 5};
printf(" Number of inversions are %d \n", mergeSort(arr, 5));
getchar();
return 0;
}
我无法想到比O(n ^ 2)更好的算法,但是this post促使我想到一些更好的方法,但是我无法应用类似的逻辑(在这里提到的)
在给定的帖子中,给出的问题是在数组中找不到反转。如果array [i]&gt; array [j]和j&gt;然后它形成一个反转。例如,序列2,4,1,3,5有三个反转(2,1),(4,1),(4,3)。
用于解决此问题的想法是合并排序算法。
在合并过程中,让我用于索引左子数组(L [])和j 对于右子阵列(R [])。在merge()的任何步骤,如果L [i]更大 比R [j],则有(mid - i + 1)反转,其中mid是 中间索引传递给合并排序的合并功能。因为离开了 和右子阵列进行排序,因此所有剩余的元素都在 left-subarray(L [i + 1],L [i + 2] ... L [mid])将大于R [j]
此逻辑的代码如下:
public void sendMessage(View view) {
AsyncTask<Void, Void, String> task = new AsyncTask<Void, Void, String>() {
@Override
protected String doInBackground(Void... params) {
try {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(getApplicationContext());
String to = notificationKey; // the notification key
AtomicInteger msgId = new AtomicInteger();
String id = Integer.toString(msgId.incrementAndGet());
Bundle data = new Bundle();
data.putString("hello", "world");
gcm.send(to, id, data);
Log.e(TAG, "sendMessage done.");
} catch (Exception ex) {
Log.e(TAG, ex.toString());
}
return null;
}
};
task.execute();
}
所以这个计数数组问题可以在类似的行上完成。
是否可以在优于O(n ^ 2)-time?
的情况下构造计数数组
答案 0 :(得分:1)
假设您保留了一个数组S,其中S [0..x]是A [0..x]的排序版本。然后当你已经计算出C_min [0..x]时计算C_min [x + 1]将相当于将A [x + 1]插入S(O(log n)操作)并在其中定位A [x + 1] S(最坏的情况是,另一个O(log n)操作)。这将使计算所有C_min O(n log n)。计算C_max将类似,但需要自己的S版本,计算C_min和C_max O(n log n)。