# 合併排序法 MergeSort ###### tags: `leetcode`,`sorting` >ref: https://www.geeksforgeeks.org/in-place-merge-sort/ > ## 基礎流程 1. 分成split/conquer兩方法,藉由分組至單個元素後兩兩比較形成有序排列,持續合併至原方法,範例為遞迴方式呼叫 2. TimeComplexity, 分組行為每次拆為一半, 需log~2~n次=>O(log~2~n),conquer次數同split 合併時需進行比較,假定為兩代合併陣列分別為m,n個元素, 最優情況為其中一組皆小於/皆大於另一組=>比較n或m次o(n),最差情況為m+n-1(每元素皆需比較過O(n)) 總時間: 分裂時間+ 合併時間 = O(logN) + O(N* logN)=>省略前向 結果為O(nlog~2~n) ![](https://i.imgur.com/XJi6AmR.png) 3. spaceComplecity: O(N) 3a.ListNode: 每次merge的dummy head: O(log~2~n) 3b.in-place Array:split記憶middle位置 : O(log~2~n),conquer時 inplace記憶 val/idx : O(log~2~2n)=>O(log~2~3n) ```java= public ListNode mergesort(ListNode m) { // separate the list ListNode middle = findMiddle(m); ListNode start2 = middle.next; middle.next = null; ListNode left = mergesort(m); ListNode right = mergesort(start2); return merge(left, right); } ``` ListNode def: ```java= public class ListNode { int val; ListNode next; ListNode() { } ListNode(int val) { this.val = val; } ListNode(int val, ListNode next) { this.val = val; this.next = next; } } ``` ```java= public ListNode findMiddle(ListNode n) { ListNode a = n; ListNode b = n; while (b != null && b.next != null) { a = a.next; b = b.next.next; } return a; } public ListNode merge(ListNode left, ListNode right) { ListNode head = new ListNode(); ListNode cur = head; // remodel the node while (left != null && right != null) { if (left.val <= right.val) { cur.next = left; left = left.next; } else { cur.next = right; right = right.next; } cur = cur.next; } // concatenate the remaining list if (left == null) { cur.next = right; } else { cur.next = left; } return head.next; } ``` ## inplace array 1. merge時需記憶idx與val做arr內數值移動 ```java= public int[] mergesort(int[] arr) { // split helper split(arr, 0, arr.length - 1); return arr; } private void split(int[] arr, int s, int e) { if (s >= e) { return; } // middle int middle = s + (e - s) / 2; // split split(arr, s, middle); split(arr, middle + 1, e); // conquer merge(arr, s, middle, e); } private void merge(int[] arr, int s, int middle, int e) { int st2 = middle + 1; if (arr[middle] <= arr[st2]) { return; } while (s <= middle && st2 <= e) { //equal condition to compare the last one if (arr[s] > arr[st2]) { int val = arr[st2]; int idx = st2; while (s < idx) { arr[idx] = arr[--idx]; } arr[s] = val; middle++;//move backward the original array insert arr[st2], the checking condition should move backward too st2++; } s++; } } } ```