zoukankan      html  css  js  c++  java
  • **(不会)数据结构--小和问题 逆序对问题

    小和问题
    在一个数组中, 每一个数左边比当前数小的数累加起来, 叫做这个数组的小和。 求一个数组的小和。
    例子:
    [1,3,4,2,5]
    1左边比1小的数, 没有;
    3左边比3小的数, 1;
    4左边比4小的数, 1、 3;
    2左边比2小的数, 1;
    5左边比5小的数, 1、 3、 4、 2;
    所以小和为1+1+3+1+1+3+4+2=16

    解:利用归并排序中,在进行两部分小组合并时,会在对比时,如果左边的比右边的小,则加上 右边个数个的左边的数  num * (right - y + 1)

    其中的某一次对比

    求小和只发生在两个小组之间。

    public class LittleSum {
    
        public int littleSum(int [] arrays){
            return mergeSort(arrays, 0, arrays.length - 1);
        }
    
        public int mergeSort(int[] arrays, int left, int right){
            if(left >= right){
                return 0;
            }
    
            int mid = left + ((right - left) >> 1);
            return mergeSort(arrays, left, mid)
                    + mergeSort(arrays, mid + 1, right)
                    + merge(arrays, left, mid, right);
        }
    
        public int merge(int[] arrays, int left, int mid, int right){
            int sum = 0;
            int[] help = new int[right - left + 1];
            int i = 0;
            int x = left, y = mid + 1;
            while(x <= mid && y <= right){
                sum += arrays[x] < arrays[y] ? arrays[x] * (right - y + 1) : 0;
                help[i++] = arrays[x] < arrays[y] ? arrays[x++] : arrays[y++];
            }
            while(x <= mid){
                help[i++] = arrays[x++];
            }
            while(y <= right){
                help[i++] = arrays[y++];
            }
            i = 0;
            while(i < help.length){
                arrays[left + i] = help[i++];
            }
            return sum;
        }
    
        public static void main(String[] args){
            int[] arrays = {1, 3, 4, 2, 5};
    
            LittleSum littleSum = new LittleSum();
            int sum = littleSum.littleSum(arrays);
            System.out.println(sum);
        }
    
    
    }
    

      

    逆序对问题
    在一个数组中, 左边的数如果比右边的数大, 则折两个数构成一个逆序对, 请打印所有逆序对 

     解:逆序对的同理,在merge的过程中,比较相应的两个数,遇到arrays[x] > arrays[y] 则从x开始,到mid结束,都比arrays[y]大,都可以构成逆序对,所以只需要将它们输出即可

    与小和相比,只有第一个while处不同,其余地方均没有改动

    public void merge(int[] arrays, int left, int mid, int right){
            int[] help = new int[right - left + 1];
            int i = 0;
            int x = left, y = mid + 1;
            while(x <= mid && y <= right){
                if(arrays[x] > arrays[y]){
                    for(int j = x; j <= mid; j++){
                        System.out.println(arrays[j] + " " + arrays[y]);
                    }
                    help[i++] = arrays[y++];
                } else{
                    sum += arrays[x] * (right - y + 1);
                    help[i++] = arrays[x++];
                }
            }
            while(x <= mid){
                help[i++] = arrays[x++];
            }
            while(y <= right){
                help[i++] = arrays[y++];
            }
            i = 0;
            while(i < help.length){
                arrays[left + i] = help[i++];
            }
        }
    

      

    剑指offer中的逆序对:会有大小,溢出的问题,用int类型,会溢出,要用long型才可以

    数组中的逆序对

    public class Solution {
        public int InversePairs(int [] array) {
            if(array == null || array.length == 0) return 0;
            long res = mergeSort(array, 0, array.length - 1);
            return (int)(res % 1000000007);
        }
    
        public long mergeSort(int[] array, int left, int right){
            if(left >= right){
                return 0;
            }
            int mid = ((right - left) >> 1) + left;
            return mergeSort(array, left, mid) 
                + mergeSort(array, mid + 1, right) 
                + merge(array, left, mid, right);
        }
    
        public long merge(int[] array, int left, int mid, int right){
            int[] help = new int[right - left + 1];
            int i = left, j = mid + 1, flag = 0;
            long res = 0;
            while(i <= mid && j <= right){
                if(array[i] < array[j]){
                    help[flag++] = array[i++];
                }else {
                    help[flag++] = array[j++];
                    res = res + (mid - i + 1);
                }
            }
            while(i <= mid){
                help[flag++] = array[i++];
            }
            while(j <= right){
                help[flag++] = array[j++];
            }
    
            for(i = 0; i < flag; i++){
                array[left + i] = help[i];
            }
            return res;
        }
    }
    

      

  • 相关阅读:
    Linux下多线程查看工具(pstree、ps、pstack)
    linux的netstat命令详解
    linux的netstat命令详解
    实例解说Linux命令行uniq
    实例解说Linux命令行uniq
    实例解说Linux命令行uniq
    linux之sort用法
    linux之sort用法
    linux之sort用法
    oracle服务器和客户端字符集的查看和修改
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/8715987.html
Copyright © 2011-2022 走看看