【发布时间】:2022-09-29 02:06:01
【问题描述】:
归并排序是最著名的排序算法之一。
在这个问题中,mergesort 将一个唯一整数数组作为参数,并返回排序后的数组。
一个数组有 n 个元素。如果数组的元素少于 2 个,则返回数组而不做任何更改。
如果数组有两个以上的元素,则将其分成左右两个数组。
左数组包含输入数组的前半部分元素,而右数组包含后半部分元素。
如果 n 为奇数,则左侧数组取中间元素。接下来,算法首先使用左数组调用自身,然后使用右数组调用自身。 之后,该算法通过将左右数组合并为一个排序数组来生成排序数组。
在这个挑战中,对输入数组中的每个元素进行计数。
最初,所有计数均为 0。
每当右侧数组中的整数 k 在左侧数组中的至少一个元素之前合并时,将计数加 1。
求归并排序算法完成后的最大计数值。
示例 arr= [2, 3, 1]
所有计数器都初始化为 0。 首先,归并排序将输入数组划分为 left = [2,3] 和 right = 1。 接下来,它使用左数组再次运行自己。它将这个数组分为 [2] 和 [3]。由于两者都已排序,因此 Example arr = {2, 9, 1] 所有计数器都初始化为 0。首先,mergesort 将输入数组分为 left = [2,3] 和 right = 1。接下来,它使用左数组再次运行自己。它将这个数组分为 [2] 和 [3]。由于两者都已排序,因此将它们合并,并且在合并期间 3 在 2 之后合并为排序顺序,因此不会将任何内容添加到计数器中。合并后,算法将 [2,3] 返回给它的调用者。接下来,初始的合并排序调用为正确的数组 1 自行运行,但由于它只有一个元素,因此不执行合并并立即返回 1。接下来,算法将 [2,3] 与1 合并。由于在合并期间右侧数组中的 1 位于左侧数组中的两个元素之前,因此我们将 1 加到计数器中。本次合并后,算法结束,处理后的最大计数为 1。
这是我的代码,以this 为参考:
public static int mergeSort(int[] a, int p, int r, Map<Integer, Integer> m, Set<String> set)
{
int c = 0;
if(p < r)
{
int q = (p + r)/2;
c = mergeSort(a, p, q, m, set);
c += mergeSort(a, q+1, r, m, set);
c += merge(a, p, q, r, m, set);
}
return c;
}
public static int merge(int[] a, int p, int q, int r, Map<Integer, Integer> m, Set<String> set)
{
//p=0, q=1, r=3
int count = 0;
int n1 = q-p+1;
int n2 = r-q;
int[] temp1 = new int[n1+1];
int[] temp2 = new int[n2+1];
for(int i=0; i<n1; i++) temp1[i] = a[p+i];
for(int i=0; i<n2; i++) temp2[i] = a[q+1+i];
temp1[n1] = Integer.MAX_VALUE;
temp2[n2] = Integer.MAX_VALUE;
int i = 0, j = 0;
for(int k=p; k<=r; k++)
{
if(temp1[i] <= temp2[j])
{
int v = temp1[i];
a[k] = v;
i++;
if(m.get(v) > k && set.add(k+\":\"+m.get(v))) { // special case where i < j and A[i] > A[j]
count++;
}
}
else
{
int v = temp2[j];
a[k] = v;
j++;
if(m.get(v) > k && set.add(k+\":\"+m.get(v))) { // special case where i < j and A[i] > A[j]
count++;
}
}
}
return count;
}
public static void main(String[] args)
{
int[] a = {2,3,1};
int count = process(a);
System.out.println(count);
}
public static int process(int[] a) {
Map<Integer, Integer> m = new HashMap<>();
for(int i=0; i<a.length; i++) {
m.put(a[i], i);
}
Set<String> set = new HashSet<>();
int countInversion = mergeSort(a, 0, a.length-1, m, set);
return countInversion;
}
当我在 Hackerrank 中使用它时,我在 15 个测试用例中只通过了 4 个测试用例。我无法找到我在此任务中做错的地方。所有都是隐藏的测试用例,所以我看不到它们。
约束:
1 <= n <= 10^5
1 <= a[i] <= 10^9
all elements are distinct
其他示例:
Input = 2,1,3
Output = 1
Input = 1,2,3,4,5,10
Output = 0
-
Map 和 Set 都是 Sorted 容器。不清楚是谁在这里进行排序。
-
相反。
HashMap和HashSet均不保证订购。元素可以按一个顺序排列,但迭代可以以完全不同的顺序检索它们。但是,看起来 O/P 代码不依赖于任何一个Collection被订购。 -
你算在两个分支中。 “参考”会这样做吗?
-
q = (p + r)/2是否导致If n is odd, the left array takes the middle element?