zoukankan      html  css  js  c++  java
  • 归并排序

    归并排序:

    先分治后归并。

    //对于归并时的临时存储数组,可以全局使用一个,而不必每次归并都重新申请
    /* 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[] = Arrays.copyOfRange(arr, l, m + 1); 
             int R[] = Arrays.copyOfRange(arr, m+1, r+1); 
        /* Merge the temp arrays */
      
            // Initial indexes of first and second subarrays 
            int i = 0, j = 0; 
      
            // Initial index of merged subarry 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) / 2; 
      
                // Sort first and second halves 
                sort(arr, l, m); 
                sort(arr, m + 1, r); 
      
                // Merge the sorted halves 
                merge(arr, l, m, r); 
            } 
        } 

     LeetCode315

    给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 nums[i] 的元素的数量。

    示例:

    输入: [5,2,6,1]
    输出: [2,1,1,0] 
    解释:
    5 的右侧有 2 个更小的元素 (2 和 1).
    2 的右侧仅有 1 个更小的元素 (1).
    6 的右侧有 1 个更小的元素 (1).
    1 的右侧有 0 个更小的元素.
    import java.util.ArrayList;
    import java.util.List;
    
    class Solution {
    
        private int[] temp;
        private int[] counter;
        private int[] indexes;
    
        public List<Integer> countSmaller(int[] nums) {
            List<Integer> res = new ArrayList<>();
            int len = nums.length;
            if (len == 0) {
                return res;
            }
            temp = new int[len];        //merge临时数组
            counter = new int[len];     //目标数组
            indexes = new int[len];     //索引数组
            for (int i = 0; i < len; i++) {
                indexes[i] = i;
            }
            mergeAndCountSmaller(nums, 0, len - 1);
            for (int i = 0; i < len; i++) {
                res.add(counter[i]);
            }
            return res;
        }
    
        /**
         * 针对数组 nums 指定的区间 [l, r] 进行归并排序,在排序的过程中完成统计任务
         *
         * @param nums  //原数组不变
         * @param l     //inclusive
         * @param r     //inclusive
         */
        private void mergeAndCountSmaller(int[] nums, int l, int r) {
            if (l == r) {
                // 数组只有一个元素的时候,没有比较,不统计
                return;
            }
            int mid = (l + r - l) / 2;
            mergeAndCountSmaller(nums, l, mid);
            mergeAndCountSmaller(nums, mid + 1, r);
            // 归并排序的优化,同样适用于该问题
            // 如果索引数组有序,就没有必要再继续计算了
            if (nums[indexes[mid]] > nums[indexes[mid + 1]]) {
                mergeOfTwoSortedArrAndCountSmaller(nums, l, mid, r);
            }
        }
    
        /**
         * 归并过程
         * [l, mid] 是排好序的
         * [mid + 1, r] 是排好序的
         *
         * @param nums
         * @param l
         * @param mid
         * @param r
         */
        private void mergeOfTwoSortedArrAndCountSmaller(int[] nums, int l, int mid, int r) {
            // 3,4  1,2
            for (int i = l; i <= r; i++) {
                temp[i] = indexes[i];
            }
            int i = l;
            int j = mid + 1;
            // 左边出列的时候,计数
            for (int k = l; k <= r; k++) {
                if (i > mid) {
                    indexes[k] = temp[j];
                    j++;
                } else if (j > r) {
                    indexes[k] = temp[i];
                    i++;
                    // 此时 j 用完了,[7,8,9 | 1,2,3]
                    // 之前的数就和后面的区间长度构成逆序
                    counter[indexes[k]] += (r - mid);
                } else if (nums[temp[i]] <= nums[temp[j]]) {
                    indexes[k] = temp[i];
                    i++;
                    // 此时 [4,5, 6   | 1,2,3 10 12 13]
                    //           mid          j
                    counter[indexes[k]] += (j - mid - 1);
                } else {
                    // nums[indexes[i]] > nums[indexes[j]] 构成逆序
                    indexes[k] = temp[j];
                    j++;
                }
            }
        }
    
        public static void main(String[] args) {
            int[] nums = new int[]{5, 2, 6, 1};
            Solution solution = new Solution();
            List<Integer> countSmaller = solution.countSmaller(nums);
            System.out.println(countSmaller);
        }
    }
  • 相关阅读:
    Problem with the SSL CA cert (path? access rights?)
    亚马逊ec2使用nginx运行tp5报502
    MySQL 5.7 聚合函数列需要先group by
    Apache服务器HTTPS未完全正确配置的处理
    《将博客搬至CSDN》
    pytorch 8 CNN 卷积神经网络
    pytorch 7 optimizer 优化器 加速训练
    pytorch 6 batch_train 批训练
    pytorch 7 save_reload 保存和提取神经网络
    pytorch 6 build_nn_quickly 快速搭建神经网络
  • 原文地址:https://www.cnblogs.com/faded828x/p/13281828.html
Copyright © 2011-2022 走看看