还有一种常见的算法没有记录,加油,输出是最好的输入。
归并排序
归并排序是建立在归并操作的一种稳定的排序算法,采用分治法实现。讲已有序的子序列合并,得到完全有序的序列;即每个子序列有序,再将两个有序表合并为一个有序表,即二路归并。仅有一个元素时,是自然有序,是最小的有序序列。
@Test
public void testMergeSort(){
int[] arr = {7,3,4,5,7,9,2,8,10,15,12};
int[] newarr = mergeSort(arr,0,arr.length - 1);
Arrays.stream(newarr).forEach(System.out::println);
}
/**
* 归并排序
* 归并排序是建立在归并操作的一种稳定的排序算法,采用分治法实现。讲已有序的子序列合并,得到完全有序的序列;
* 即每个子序列有序,再将两个有序表合并为一个有序表,即二路归并。仅有一个元素时,是自然有序,是最小的有序序列。
* 7,3,4,5,7,9,2,8,10,15,12,初始化合并的数组
* 7,3,4,5,7,9 和 2,8,10,15,12
* [7,3,4] [7,9 ] 和 [2,8,10] [15,12]
* [7,3] [4] [7][9] 和 [2,8]
* @param
*/
public int[] mergeSort(int[] nums, int left, int right) {
//仅有一个元素时,就是自然有序的数组
if (left == right)
return new int[] { nums[left] };
//从此为止把数据分成两个子数据
int middle = left + (right - left )/2;
int [] leftArr = mergeSort(nums,left,middle);
int[] rightArr = mergeSort(nums,middle + 1,right);
System.out.println("leftLenth : " + leftArr.length + " rightLenth : " + rightArr.length);
int[] megeArr = new int[right-left + 1];
int index = 0,leftI = 0,rightI = 0;
//把两个有序的子数组合并为一个新数组
while (leftI < leftArr.length && rightI < rightArr.length){
if(leftArr[leftI] <= rightArr[rightI]){
megeArr[index++] = leftArr[leftI++];
}else{
megeArr[index++] = rightArr[rightI++];
}
}
while (leftI < leftArr.length)
megeArr[index++] = leftArr[leftI++];
while ( rightI < rightArr.length)
megeArr[index++] = rightArr[rightI++];
return megeArr;
}
时间复杂度
-
分割过程:每次递归调用时,数组的大小减半,直到每个子数组只包含一个元素。这个过程的时间复杂度是O(n log n),因为每次递归调用都会将问题规模减半,直到达到基本情况(单个元素),这个过程需要进行log n次。
-
合并过程:在合并阶段,每次合并两个有序的子数组合并成一个有序的数组,这个过程的时间复杂度是O(n),因为需要遍历所有元素。由于每次递归调用都会将问题规模减半,直到所有元素都被合并,这个过程的时间复杂度也是O(n log n)。
综合以上两个阶段,归并排序的总时间复杂度是O(n log n)。这个时间复杂度在最好情况、最坏情况和平均情况下都是相同的,因为归并排序的性能不受输入数据分布的影响,始终保持稳定。
此外,归并排序的空间复杂度为O(n),因为在合并过程中需要额外的空间来存储临时数据。