日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构与算法--数组中的逆序对

發布時間:2023/12/4 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构与算法--数组中的逆序对 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 題目:在數組中的兩個數字如果簽名一個數字大于后面的數組,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。

  • 案例:輸入數組{7,5,6,4}中一共有5個逆序對分別是{7,6},{7,5},{7,4},{6,4},{5,4}

  • 如上題描述,最簡單的方案就是雙循環遍歷整個數組,掃描第一個數字的時候讓他與其他數字逐個比較,記錄下比他小的數字并且累加一,這個類似冒泡排序的一個算法

  • 雙循環的方案時間復雜度與冒泡排序是一樣的都是O(n2),應該有更快的方案

  • 方案二:

    • 還是用{7,5,6,4}作為案例分析,既然我們不能拿到第一個后與后面列表逐個比較,那么我們拆解開看能否得到更優方案
    • 我們將數組按從左到右拆解成一個元素一個元素的單個數組
    • 接著一遍合并相鄰的子數組,一遍統計逆序對的數目
    • 我們用如下圖解
  • 第一步,我們將數組每次拆解一半,知道數組只剩下1 個或者2個,我們此處用最好理解的方案,拆解成獨立的一個

  • 第二步,逐個比較相鄰的,7 < 5 是一個逆序對,我們應該count +1,并且將兩個獨立數組合并成一個有序數組,同理6與4 也是一樣,得到兩個數組,分別是{7,5}, {6,4}

  • 第三部接著合并得到的兩個數組,并統計,如下圖中,當left指針指向7 ,right指向6 此時left > right,

  • 因為此時兩個數組都是順序的,那么left指向的數據比 第二個數組中所有數都要大

  • 那么count疊加次數應該是第二個數組的長度,或者說是right指向的數據的下標大小+1

  • 接著移動left,right,并且將較大的數放入合并的數組中

  • 如上步驟和我們先進行拆解,然后對子數組逐個進行統計排序的方式和我們之前 文章:數據結構與算法–排序算法總結(動圖演示) 講到的歸并排序的思想是一樣的

  • 只不過我們之前的實現中歸并排序拆解的時候選擇的是拆解成2 個,因為這樣可減少遞歸的次數

  • 此時我們選擇拆解成1個,是因為我們目的是需要統計次數,如果拆解成2個,必須在對這兩個進行單獨排序的時候單獨統計,這樣多了多余的邏輯

  • 經如上分析有如下代碼:

/*** 找出數組中所有逆序對 例如:* {7,5,6,4} => 75,76,74,54,64* @author liaojiamin* @Date:Created in 14:50 2021/6/11*/ public class InversePairs {public static Integer countInverse = 0;public static Integer[] mergeSortFindPairs(Integer[] array){if(array == null || array.length <= 1){return array;}if(array.length < 2){return array;}Integer middle = array.length/2;Integer[] left = Arrays.copyOfRange(array, 0, middle);Integer[] right = Arrays.copyOfRange(array, middle, array.length);return merge(mergeSortFindPairs(left), mergeSortFindPairs(right));}public static Integer[] merge(Integer[] left, Integer[] right){Integer[] mergeArray = new Integer[left.length + right.length];Integer targetPosition = mergeArray.length-1;Integer leftPosition = left.length -1;Integer rightPosition = right.length -1;while (targetPosition >= 0){if(leftPosition >=0 && rightPosition >= 0){if(left[leftPosition] > right[rightPosition]){countInverse+=(rightPosition+1);mergeArray[targetPosition--] = left[leftPosition--];}else {mergeArray[targetPosition--] = right[rightPosition--];}}else {if(leftPosition < 0){while (rightPosition >= 0){mergeArray[targetPosition--] = right[rightPosition--];}}else {while (leftPosition >= 0){mergeArray[targetPosition--] = left[leftPosition--];}}}}return mergeArray;}public static void main(String[] args) {Integer[] array = {1,3,44,22,31,4,0,32,14,16,32,9,4,7,23,555,12,123,456};array = mergeSortFindPairs(array);for (int i = 0; i < array.length; i++) {System.out.println(array[i]);}System.out.println(countInverse);} }
  • 如上算法中與歸并算法一樣時間復雜度是O(nlogn),比最直觀的方案一O(n2)要快,但是我們需要額外一個長度為n的數組,空間復雜度是O(n),我們用空間換時間的算法。

上一篇:數據結構與算法–第一個只出現一次的字符
下一篇:數據結構與算法–兩個鏈表中第一個公共節點

總結

以上是生活随笔為你收集整理的数据结构与算法--数组中的逆序对的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。