1. 程式人生 > >分治演算法(歸併排序、一維點對、HDU-1007)

分治演算法(歸併排序、一維點對、HDU-1007)

分治演算法的基本思想是將一個規模為N的問題分解為K個規模較小的子問題,這些子問題相互獨立且與原問題性質相同。求出子問題的解,就可得到原問題的解。

分治法解題的一般步驟:

  1. 分解,將要解決的問題劃分成若干規模較小的同類問題;
  2. 求解,當子問題劃分得足夠小時,用較簡單的方法解決;
  3. 合併,按原問題的要求,將子問題的解逐層合併構成原問題的解。

在認識分治之前很有必要先了解一下遞迴,當然,遞迴也是最基本的程式設計問題,一般接觸過程式設計的人都會對遞迴有一些認識.為什麼要先了解遞迴呢?你看,根據上面所說的,我們就要將一個問題分成若干個小問題,然後一一求解並且最後合併,這就是一個遞迴的問題,遞迴的去分解自身,遞迴的去解決每一個小問題,然後合併…

關於遞迴,這裡舉一個最簡單的例子,求N!,程式碼如下:

public int getFactorial(int n) {
    if (n == 1) {
        return n;
    } else {
        return n * getFactorial(n-1);
    }
}

有了遞迴的鋪墊,我們開始看看分治演算法相關的一些常見問題:

1、歸併排序

歸併排序是建立在歸併操作上的一種有效的排序演算法。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。

首先要把需要排序的陣列分解成若干個小陣列,直到不可再分為止,之後再將這些小陣列通過簡單的比較排序之後進行合併,下面先看看合併陣列的示例:

package sort;

public class SortTest {
    public static void main(String[] args) {
        int[] num1 = {1, 3, 4, 7, 9};
        int[] num2 = {2, 5, 7, 10};
        int[] numMeger = new int[num1.length + num2.length];
        MegerArray(num1, num2, num1.length, num2.length, numMeger);

        for
(int i = 0; i < numMeger.length; i++) { System.out.print(numMeger[i] + " "); } } public static void MegerArray(int[] num1, int[] num2, int n1, int n2, int[] numMeger) { int i = 0; int j = 0; int k = 0; while (i < n1 && j < n2) { if (num1[i] < num2[j]) { numMeger[k++] = num1[i++]; } else { numMeger[k++] = num2[j++]; } } while (i < n1) { numMeger[k++] = num1[i++]; } while (j < n2) { numMeger[k++] = num2[j++]; } } }

有了之前遞迴和合並的前提之後就可以進行歸併排序了,基本思路就是將陣列分成二組A,B,如果這二組組內的資料都是有序的,那麼就可以很方便的將這二組資料進行排序。如何讓這二組組內資料有序了?

可以將A,B組各自再分成二組。依次類推,當分出來的小組只有一個數據時,可以認為這個小組組內已經達到了有序,然後再合併相鄰的二個小組就可以了。這樣通過先遞迴的分解數列,再合併數列就完成了歸併排序。
示例如下:

package sort;

public class SortTest {
    public static void main(String[] args) {
        int[] num = {2, 8, 4, 7, 10, 9, 14};
        int[] numSort = new int[num.length];
        mergeSort(num, 0, num.length-1, numSort);
        for (int i = 0; i < num.length; i++) {
            System.out.print(num[i] + " ");
        }
        System.out.println();
        for (int i = 0; i < numSort.length; i++) {
            System.out.print(numSort[i] + " ");
        }
    }

    public static void mergeSort(int[] num, int first, int last, int[] temp) {

        if (first < last) {
            int mid = (first + last) / 2;
            mergeSort(num, first, mid, temp);
            mergeSort(num, mid+1, last, temp);
            MegerArray(num, first, mid, last, temp);
        }
    }

    public static void MegerArray(int[] num, int first, int mid, int last, int[] temp) {
        int i = first;
        int j = mid+1;
        int m = 0;
        while (i <= mid && j <= last) {
            if (num[i] < num[j]) {
                temp[m++] = num[i++];
            } else {
                temp[m++] = num[j++];
            }
        }

        while (i <= mid) {
            temp[m++] = num[i++];
        }

        while (j <= last) {
            temp[m++] = num[j++];
        }

        for (int n = 0; n < m; n++) {
            num[first + n] = temp[n];
        }
    }
}

相關推薦

分治演算法歸併排序HDU-1007

分治演算法的基本思想是將一個規模為N的問題分解為K個規模較小的子問題,這些子問題相互獨立且與原問題性質相同。求出子問題的解,就可得到原問題的解。 分治法解題的一般步驟: 分解,將要解決的問題劃分成若干規模較小的同類問題; 求解,當子問題劃分得足夠小時,

【NOJ1002】【演算法實驗】【分治演算法歸併排序

1002.歸併排序 時限:1000ms 記憶體限制:10000K  總時限:3000ms 描述 給定一個數列,用歸併排序演算法把它排成升序。 輸入 第一行是一個整數n(n不大於10000),表示要排序的數的個數; 下面一行是用空格隔開的n個整數。 輸出

分治演算法 ------二分歸併排序

  https://www.youtube.com/watch?v=EMw1rwQmD3w&index=27&list=PLvdLBjhf_tgqq0ESrSd4rH8bXLmOlxN2J 二分歸併排序   選擇中間的數,把陣列對半劃分。分別

分治演算法歸併排序

歸併排序分兩步: 第一步:將陣列遞迴分為兩部分。 第二步:將兩部分陣列遞迴合併為一個數組。 def mergeSort(l1): print('mergeSort:',l1) length = len(l1) if length

演算法分析——排序演算法歸併排序複雜度分析遞迴樹法

前面對演算法分析的一些常用的 漸進符號 做了簡單的描述,這裡將使用歸併排序演算法做為一個實戰演練。 這裡首先假設讀者對歸併排序已經有了簡單的瞭解(如果不瞭解的同學可以自行百度下歸併排序的原理)。瞭解此演算法的同學應都知道,歸併排序的主要思想是分而治之(簡稱分治)。分治演算法

演算法分析——排序演算法歸併排序複雜度分析代換法

上篇文章中我們對歸併排序的時間複雜度使用遞迴樹法進行了簡答的分析,並得出了結果歸併排序的時間複雜度為,這裡將使用代換法再進行一次分析。使用代換法解遞迴式的時候,主要的步驟有兩步:         1)猜測解的結果         2)使用數學歸納法驗證猜測結果      

演算法分析——排序演算法歸併排序複雜度分析主定理法

       前兩篇文章中分別是要用遞迴樹、代換法對歸併排序的時間複雜度進行了簡單的分析和證明,經過兩次分析後,我們發現遞迴樹法的特點是:可以很直觀的反映出整個歸併排序演算法的各個過程,但因為要畫出遞迴樹所以比較麻煩,所以遞迴樹演算法更適合新手,因為它可以讓分析者更直觀、簡易

分治演算法歸併排序,快速排序和漢諾塔

1介紹 分治演算法已經是本人所寫的常用算法系列的第三個了,可能只會寫這一節,對比動態規劃與貪心演算法我們來認識一下分治演算法。 從思路上來看: (1)動態規劃:多階段過程轉化為一系列單階段問題,利用各階段之間的關係,逐個求解。每一個階段的最優解是基於前一個階段的最優解。

分治演算法--歸併排序

歸併排序 最近上演算法課,老師講到分治演算法那塊了,感覺上課是認真聽了的,可是那個段子手老師講幾個笑話我就忘完了,很尷尬,所以以後她每講一章,自己還是總結下哈 分治演算法的理解 就我個人來說,對分治演算法理解很簡單,就三個字 分 解 合 分:就是把大

演算法排序演算法排序氣泡排序快速排序

第一次排序:首先,找一個"基準數",比如5,然後,先從右到左,找到第一個小於基準數的數,4,再從左到右,找到第一個大於基準數的數,9將它們進行交換,5,1,4,26,2,9,5,7,52,21繼續從右到左,尋找小於基準數的數,從左到右,尋找大於基準數的數,並交換,直到兩個相遇,5,1,4,2,26,9,5,7

排序演算法氣泡排序選擇排序插入排序歸併排序快速排序希爾排序

氣泡排序           核心:                       相鄰元素兩兩比較,大的往後放。第一次比較完畢以

常見比較排序演算法的實現歸併排序快速排序排序選擇排序插入排序希爾排序

這篇部落格主要實現一些常見的排序演算法。例如: //氣泡排序 //選擇排序 //簡單插入排序 //折半插入排序 //希爾排序 //歸併排序 //雙向的快速排序(以及快速排序的非遞迴版本) //單向的快速排序 //堆排序 對於各個演算法的實現

演算法淺談——分治演算法歸併快速排序(附程式碼和動圖演示)

在之前的文章當中,我們通過海盜分金幣問題詳細講解了遞迴方法。 我們可以認為在遞迴的過程當中,我們通過函式自己呼叫自己,將大問題轉化成了小問題,因此簡化了編碼以及建模。今天這篇文章呢,就正式和大家聊一聊將大問題簡化成小問題的分治演算法的經典使用場景——排序。 排序演算法 排序演算法有很多,很多博文都有總結

題目描述 在一個二數組中每個一維數組的長度相同,每一行都按照從左到右遞增的順序排序,每列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二數組和一個整數,判斷數組中是否含有該整數。

這樣的 -i 一個 整數 描述 輸入 遞增 lse i+1 題目描述 在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。 1

《資料結構與演算法》之排序演算法插入排序希爾排序

3、插入排序 插入排序的基本操作就是將一個數據插入到已經排好序的有序資料中,從而得到一個新的、個數加一的有序資料,演算法適用於少量資料的排序,時間複雜度為O(n^2),是穩定的排序方法。插入演算法把要排序的陣列分成兩部分:第一部分包含了這個陣列的所有元素,但將最後一個元素除外(讓陣列多一個空間才

《資料結構與演算法》之排序演算法氣泡排序選擇排序

排序(Sorting) 是計算機程式設計中的一種重要操作,它的功能是將一個數據元素(或記錄)的任意序列,重新排列成一個關鍵字有序的序列。 排序演算法分類: 一、非線性時間比較類排序 1、交換排序(氣泡排序、快速排序) 2、插入排序(簡單插入排序、布林排序) 3、選擇排序(簡單選擇

【Java】 大話資料結構(17) 排序演算法(4) 歸併排序 資料結構與演算法合集 資料結構與演算法合集

本文根據《大話資料結構》一書,實現了Java版的堆排序。 更多:資料結構與演算法合集 基本概念   歸併排序:將n個記錄的序列看出n個有序的子序列,每個子序列長度為1,然後不斷兩兩排序歸併,直到得到長度為n的有序序列為止。   歸併方法:每次在兩個子序列中找到較小的那一個賦值給合併序列(通過指標進行操

O(n*logn)級別的演算法之一歸併排序及其優化

原理: 設兩個有序的子序列(相當於輸入序列)放在同一序列中相鄰的位置上:array[low..m],array[m + 1..high],先將它們合併到一個區域性的暫存序列 temp (相當於輸出序列)中,待合併完成後將 temp 複製回 array[low..high]中,從而完成排序。 在具體的合併過

排序演算法歸併排序關鍵詞:資料結構/演算法/排序演算法/歸併排序

假定:有 1 個亂序的數列 nums ,其中有 n 個數。 要求:排好序之後是 從小到大 的順序。 歸併排序演算法 程式碼 def merge(a, b): res = [] A = 0 B = 0 while A<len(a) and B<len(b

排序演算法之——歸併排序兩種方法及其優化

1 public class MergeX implements Comparable<Merge> {// 歸併排序(優化後) 2 private static Comparable[] aux; 3 4 private static boolean less(C