【问题标题】:Merge sort find count of shifts合并排序查找班次计数
【发布时间】: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 容器。不清楚是谁在这里进行排序。
  • 相反。 HashMapHashSet 均不保证订购。元素可以按一个顺序排列,但迭代可以以完全不同的顺序检索它们。但是,看起来 O/P 代码不依赖于任何一个 Collection 被订购。
  • 你算在两个分支中。 “参考”会这样做吗?
  • q = (p + r)/2 是否导致 If n is odd, the left array takes the middle element

标签: java arrays algorithm


【解决方案1】:

修改经典的合并排序算法,只用一个计数器来跟踪:

每当右侧数组中的整数 k 在左侧数组中的至少一个元素之前合并时,将计数加 1。

class MergeSort {
    public int count = 0;
    void merge(int arr[], int p, int q, int r) {
        int n1 = q - p + 1;
        int n2 = r - q;
        int L[] = new int[n1];
        int M[] = new int[n2];
        for (int i = 0; i < n1; i++)
            L[i] = arr[p + i];
        for (int j = 0; j < n2; j++)
            M[j] = arr[q + 1 + j];
        int i, j, k;
        i = 0;
        j = 0;
        k = p;
        while (i < n1 && j < n2) {
            if (L[i] <= M[j]) {
                arr[k] = L[i];
                i++;
            } else {
                if (i != n1) {
                    count += 1;
                }
                arr[k] = M[j];
                j++;
            }
            k++;
        }
        while (i < n1) {
            arr[k] = L[i];
            i++;
            k++;
        }
        while (j < n2) {
            arr[k] = M[j];
            j++;
            k++;
        }
    }

    void mergeSort(int arr[], int l, int r) {
        if (l < r) {
            int m = (l + r) / 2;
            mergeSort(arr, l, m);
            mergeSort(arr, m + 1, r);
            merge(arr, l, m, r);
        }
    }
}

【讨论】:

    【解决方案2】:
    /* Java program for Merge Sort */
    class MergeSort {
        // Merges two subarrays of arr[].
        // First subarray is arr[l..m]
        // Second subarray is arr[m+1..r]
        void merge(int arr[], int l, int m, int r)
        {
            // Find sizes of two subarrays to be merged
            int n1 = m - l + 1;
            int n2 = r - m;
    
            /* Create temp arrays */
            int L[] = new int[n1];
            int R[] = new int[n2];
    
            /*Copy data to temp arrays*/
            for (int i = 0; i < n1; ++i)
                L[i] = arr[l + i];
            for (int j = 0; j < n2; ++j)
                R[j] = arr[m + 1 + j];
    
            /* Merge the temp arrays */
    
            // Initial indexes of first and second subarrays
            int i = 0, j = 0;
    
            // Initial index of merged subarray array
            int k = l;
            while (i < n1 && j < n2) {
                if (L[i] <= R[j]) {
                    arr[k] = L[i];
                    i++;
                }
                else {
                    arr[k] = R[j];
                    j++;
                }
                k++;
            }
    
            /* Copy remaining elements of L[] if any */
            while (i < n1) {
                arr[k] = L[i];
                i++;
                k++;
            }
    
            /* Copy remaining elements of R[] if any */
            while (j < n2) {
                arr[k] = R[j];
                j++;
                k++;
            }
        }
    
        // Main function that sorts arr[l..r] using
        // merge()
        void sort(int arr[], int l, int r)
        {
            if (l < r) {
                // Find the middle point
                int m = l + (r - l) / 2;
    
                // Sort first and second halves
                sort(arr, l, m);
                sort(arr, m + 1, r);
    
                // Merge the sorted halves
                merge(arr, l, m, r);
            }
        }
    
        /* A utility function to print array of size n */
        static void printArray(int arr[])
        {
            int n = arr.length;
            for (int i = 0; i < n; ++i)
                System.out.print(arr[i] + " ");
            System.out.println();
        }
    
        // Driver code
        public static void main(String args[])
        {
            int arr[] = { 12, 11, 13, 5, 6, 7 };
    
            System.out.println("Given Array");
            printArray(arr);
    
            MergeSort ob = new MergeSort();
            ob.sort(arr, 0, arr.length - 1);
    
            System.out.println("\nSorted array");
            printArray(arr);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-07-12
      • 1970-01-01
      • 1970-01-01
      • 2015-07-08
      • 2015-07-09
      • 1970-01-01
      • 2021-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多