AcWing787归并排序
题目:
题目大意:
归并排序
数据范围:
如图所示
思路:
将数组nums[l, r] (初始时l = 0, r = n - 1),递归的分成[l, mid]、[mid + 1, r] 两个区间,其中 mid = l + r >>1,在 l >= r 及区间中只有一个元素时结束递归,开始回溯,回溯时将 [l, mid]、[mid + 1, r] 进行有序合并,合并的具体做法是新开一个长度为 r - l + 1的数组s,遍历左右两区间,每次选取较小的那个元素放在s中,由于区间长度有可能不一样,所以注意处理区间剩余的元素。最后将s覆盖到nums中。
代码:
import java.util.Scanner;
public class Main {
public static int N = 100010;
public static int[] nums = new int[N];
public static void mergeSort(int[] nums, int l, int r){
int mid = l + r >> 1;
if (l >= r)
return;
mergeSort(nums, l, mid);
mergeSort(nums, mid + 1, r);
int[] s = new int[r - l + 1];
int cnt = 0;
int i = l, j = mid + 1;
while (i <= mid && j <= r){
if (nums[i] < nums[j]){
s[cnt ++ ] = nums[i ++ ];
}else{
s[cnt ++ ] = nums[j ++ ];
}
}
while (i <= mid){
s[cnt ++ ] = nums[i ++ ];
}
while (j <= mid){
s[cnt ++ ] = nums[j ++ ];
}
for (i = 0, j = l; i < cnt && j <= r; i ++ , j ++ ){
nums[j] = s[i];
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
for (int i = 0; i < n; i ++ ){
nums[i] = scanner.nextInt();
}
mergeSort(nums, 0, n - 1);
for (int i = 0; i < n; i ++ ){
System.out.print(nums[i] + " ");
}
}
}
时空复杂度分析等:
-
时间复杂度 : O(nlogn):
- 分析:将一个长度为n的数组每次分为两半,分到区间长度为1时,要分logn次,也就是说要递归logn层,每层的时间复杂度都为O(n),所以总时间复杂度为O(nlogn)。
-
空间复杂度 : O(n)。