package _Sort.Algorithm
/**
* https://www.geeksforgeeks.org/merge-sort/
* https://www.cnblogs.com/chengxiao/p/6194356.html
* best/worst/average Time complexity are O(nlogn), Space complexity is O(n), stable
* # is Divide and Conquer algorithm
* Basic idea
* 1. find the middle point to divide the array into two halves;
* 2. Call MergeSort for first halves;
* 3. Call MergeSort for second halves;
* 4. Merge two halves;
* */
class MergeSort {
fun sortArray(array: IntArray): IntArray {
//create temp array first, avoid create temp in recursion
val tempArray = IntArray(array.size)
val left = 0
val right = array.size - 1
sort(array, left, right, tempArray)
//printArray(array)
return array
}
private fun printArray(array: IntArray) {
for (item in array) {
print("$item,")
}
}
private fun sort(array: IntArray, left: Int, right: Int, tempArray: IntArray) {
if (left < right) {
val mid = (left + right) / 2
sort(array, left, mid, tempArray)
sort(array, mid + 1, right, tempArray)
merge(array, left, mid, right, tempArray)
}
}
private fun merge(array: IntArray, left: Int, mid: Int, right: Int, tempArray: IntArray) {
var i = left
var j = mid + 1
var k = 0
//merge the sub arrays
while (i <= mid && j <= right) {
if (array[i] <= array[j]) {
tempArray[k] = array[i]
i++
} else {
tempArray[k] = array[j]
j++
}
k++
}
//add remaining elements of L[]
while (i <= mid) {
tempArray[k] = array[i]
i++
k++
}
//add remaining elements of R[]
while (j <= right) {
tempArray[k] = array[j]
j++
k++
}
//copy temp into original
k=0
for (i in left until right+1) {
array[i] = tempArray[k++]
}
}
}