1. 程式人生 > >求陣列中的逆序對 分治法

求陣列中的逆序對 分治法


題目分析:先求前面一半陣列的逆序數,再求後面一半陣列的逆序數,然後求前面一半陣列比後面一半陣列中大的數的個數(也就是逆序數),這三個過程加起來就是整體的逆序數目了。這類似與歸併排序,歸併排序的思想就是把前一段排序,後一段排序,然後再整體排序。而且,歸併排序的規程中,需要判斷前一半陣列和後一半陣列中當前數字的大小。這也就是剛剛描述的逆序的判斷過程了。如果前一半陣列的當前數字大於後一半陣列的當前數字,那麼這就是一個逆序數。利用歸併排序的過程中,在每一次歸併兩個陣列的時候,如果左陣列比右陣列大,那麼著就是一個逆序。記錄所有左陣列比右陣列大的情況,就是全部的逆序數目。

具體解析:

               圖片來自於兼職

offer

先把陣列分解成兩個長度為2的子陣列,再把這兩個子陣列分解成兩個長度為1的子陣列。接下來一邊合併相鄰的子陣列,一邊統計逆序對的數目。在第一對長度為1的子陣列{7}{5}7>5,因此(7,5)組成一個逆序對。同樣在第二對長度為1的子陣列{6}{4}中也有逆序對(6,4),由於已經統計了這兩對子陣列內部的逆序對,因此需要把這兩對子陣列進行排序,避免在之後的統計過程中重複統計。

逆序對的總數=左邊陣列中的逆序對的數量+右邊陣列中逆序對的數量+左右結合成新的順序陣列時中出現的逆序對的數量;

//陣列中的逆序對

    public static int InversePairs(int[] array){

        if(array==null||array.length<=1)

            return 0;

        int[] copy = new int[array.length];

        for(int i=0;i<array.length;i++){

            copy[i] = array[i];

        }

        return mergeCount(array, copy, 0, array.length-1);

    }

    public static int mergeCount(int[] array, int[] copy, int start, int end){

        if(start==end){

            copy[start] = array[start];

            return 0;

        }

        int mid = (start+end)>>1;

        int leftCount = mergeCount(copy, array, start, mid);

        int rightCount = mergeCount(copy, array, mid+1, end);

        int i = mid;//i初始化為前半段最後一個數字的下標

        int j = end;//j初始化為後半段最後一個數字的下標

        int index = end;//輔助陣列複製的陣列的最後一個數字的下標

        int count = 0;//計數--逆序對的數目

        while(i>=start&&j>=mid+1){

            if(array[i]>array[j]){

                copy[index--] = array[i--];

                count += j-mid;

            }else{

                copy[index--] = array[j--];

            }

        }

        for(;i>=start;i--){

            copy[index--] = array[i];

        }

        for(;j>=mid+1;j--){

            copy[index--] = array[j];

        }

        return leftCount+rightCount+count;

    }

相關推薦

陣列 治法

題目分析:先求前面一半陣列的逆序數,再求後面一半陣列的逆序數,然後求前面一半陣列比後面一半陣列中大的數的個數(也就是逆序數),這三個過程加起來就是整體的逆序數目了。這類似與歸併排序,歸併排序的思想就是把前一段排序,後一段排序,然後再整體排序。而且,歸併排序的規程中,需要判

治法)P1908 洛谷

style 說明 scan using lis region namespace 一個 bsp 題目描述 貓貓TOM和小老鼠JERRY最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。最近,TOM老貓查閱到一個人類稱之為&ldq

演算法導論習題---n個元素任何排列的數量

問題描述: 設A[1…n]是一個包含n個不同數的陣列。如果在i < j的情況下,有A[i] > A[j],則(i,j)就稱為A中的一個逆序對(inversion),(逆序對的元素是下標,而不是數組裡的值)。給出一個演算法,它能用Θ(nlgn)的最壞

Codeforces Round #510 (Div. 2) A 模擬 B列舉 C D離散化+樹狀陣列

A Code: #include <bits/stdc++.h> #define LL long long #define INF 0x3f3f3f3f using namespace s

(演算法導論習題解problem2.4)尋找一個序列的數量

#include <stdio.h>void display(int array[], int size){    int i;    for (i =0; i < size; ++i)    {        printf("%d ", array[i]);    }    printf(

陣列的對數

class Solution { public: int InversePairs(vector<int> data) { if(data.size()<=1){ return 0;

樹狀陣列

## 逆序對的概念   在一個有 $n$ 個元素的陣列 $A$ 中,如果存在 $1 \leqslant i A_j$ ,則稱 $$ 為 $A$ 的一個逆序對。我們熟知的排序其實就是一個消滅逆序對的過程。求一個數組的逆序對數目,我們可以用歸併排序,或者用我們今天的主角樹狀陣列,還不會樹狀陣

陣列的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個。輸入一個數組,出這個陣列的總數P。並將P1000000007取模的結果輸出。

 /*        最簡單的思路:陣列的所有數兩兩比較,進行累加,空間複雜度為O(n^2)  */ class Solution { public: int InversePairs(vector<int> data) { int P

POJ 2299 治法數列(歸併排序)

Ultra-QuickSort Time Limit: 7000MS Memory Limit: 65536K Total Submissions: 50482 Accepted: 18516 Description In this proble

陣列的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個。輸入一個數組,出這個陣列的總數P。並將P1000000007取模的結果輸出。 即輸出P%100000000

分析:可以利用兩層for迴圈,從頭開始遍歷查詢每一個元素的逆序對數,然後求總和。也可以利用歸併排序的思想來求解。下面是利用歸併排序的思想求解 public class Solution{public int InversePairs(int[] array) {if (ar

離散化及樹狀陣列

用樹狀陣列求逆序對的時候注意:要統計b[i]-1的字首和,因為可能有相同值的元素 不去重離散化: sort(a+1, a+n+1, cmp); for(int i=1; i<=n; i++) { if(i == 1 || a[i].val != a[i-1].val) { to

牛客網——陣列

很久沒玩過oj,今天刷了幾道題,感覺好吃力。果然刀還是要磨磨才鋒利 題目描述 在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。 輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007

劍指offer:(36)時間效率和空間效率的平衡 :陣列

在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007 package cn.com.jianzhioffer; public class S

治法陣列最大元素

原創 在陣列A[n]中,設m是其中最大元素,則m=max(A[0],max( A[1]……A[n-1]); 同理 max( A[1]……A[n-1] ) = max ( A[1] , max( A[2]……A[n-1] ); 設函式findMax( int index ) 是尋找陣列中最大

劍指offer系列(十三)陣列,兩個連結串列的第一個公共結點,數字在排序陣列出現的次數

陣列中的逆序對 題目描述 在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007 輸入描述: 題目保證輸入的陣列中沒有的相同的數字

樹狀陣列【TSOJ 1232】

傳送門就不傳送了,你們也傳送不進來; 就是一個求逆序對的裸題; 直接離散化+樹狀陣列就完事了。 樹狀陣列區間更新和區間查詢寫 這題總是不對; 我也不知道為啥,過幾天再研究吧。 單點更新的樹狀陣列寫對了; 總之就是如果用樹狀陣列的話一定要離散化。 下面是程式碼: #in

《劍指offer》系列 陣列(Java)

連結 牛客:陣列中的逆序對 題目描述 在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007 輸入描述 題目保證輸入的陣

poj2299樹狀陣列入門,

今天入門了樹狀陣列 習題連結 https://blog.csdn.net/liuqiyao_01/article/details/26963913 離散化資料:用一個數組來記錄每個值在數列中的排名,不能用map,會超時 開結構體儲存每個數在數列中原來的位置,排序後用a陣列求出原來狀態下

(劍指offer)陣列

時間限制:2秒 空間限制:32768K 熱度指數:228207 本題知識點: 陣列 題目描述 在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000

【劍指offer】陣列(校正書上錯誤)【歸併排序】

題目描述 在陣列中的兩個數字,如果前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個陣列中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007 題目保證輸入的陣列中沒有的相同的數字 資料範圍: