归并排序
- 算法时间复杂度: $O(NlogN)$
- 相比冒泡、选择等时间复杂度为 $O(N^2)$ 的排序算法,没有浪费比较行为;
- 插入排序时即便使用二分查找插入位置,也需要将插入位置后的元素依次向右移动,每次插入复杂度不是 $O(1)$。
递归方法
- Java 实现
1 | public class MergeSort { |
输出内容:
1 | [12, 3, 2, 6, 4, 8, 6, 0, 9, 3] |
- Rust 实现
1 |
|
非递归方法
- Java 实现
1 | public static <T extends Comparable<T>> void mergeSortLoop(T[] array) { |
- Rust 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
fn test_loop_merge_sort() {
for _ in 0..100 {
let mut array0: [u8; 32] = rand::random();
let mut array1 = array0.clone();
array0.loop_merge_sort();
array1.sort();
assert_eq!(array0, array1);
}
}
impl<T: Ord + Clone> MergeSort for [T] {
fn merge_sort(&mut self) {
//...
}
fn loop_merge_sort(&mut self) {
let len = self.len();
if len < 2 {
return;
}
let mut merge_size: usize = 1;
while merge_size < len {
let mut left = 0;
while left < len {
let mid = left + merge_size;
if mid >= len {
break;
}
let right = (mid + merge_size).min(len);
// merge sorted
let mut vec = Vec::with_capacity(right - left);
let mut i = left;
let mut j = mid;
while i < mid && j < right {
if self[i] <= self[j] {
vec.push(self[i].clone());
i += 1;
} else {
vec.push(self[j].clone());
j += 1;
}
}
while i < mid {
vec.push(self[i].clone());
i += 1;
}
while j < right {
vec.push(self[j].clone());
j += 1;
}
(&mut self[left..right]).clone_from_slice(&vec);
left = right;
}
if merge_size > len >> 1 {
break;
}
merge_size <<= 1;
}
}
}
1 |
|
求数组的小和
在一个数组中,一个数左边比它小的数的总和,叫数的小和,所有数的小和加起来叫数组小和。求数组小和。
例子:
[1, 3, 4, 2, 5]
1
左边比自己小的数:没有3
左边比自己小的数:1
4
左边比自己小的数:1
3
2
左边比自己小的数:1
5
左边比自己小的数:1
3
4
2
所以,数组的小和为 $1 + 1 + 3 + 1 + 1 + 3 + 4 + 2 = 16$
- Java 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public class SmallSum {
public static void main(String[] args) {
System.out.println(smallSum(new int[]{1, 3, 4, 2, 5}) + " == " + getSmallSumSimple(new int[]{1, 3, 4, 2, 5}));
}
static int getSmallSumSimple(int[] array) {
int smallSum = 0;
for (int i = 0; i < array.length; ++i) {
for (int j = 0; j < i; ++j) {
if (array[j] < array[i]) {
smallSum += array[j];
}
}
}
return smallSum;
}
static int smallSum(int[] array) {
int[] help = new int[array.length];
return doMergeSmallSum(array, help, 0, help.length);
}
static int doMergeSmallSum(int[] array, int[] help, int start, int end) {
if (end - start < 2) {
return 0;
}
int mid = start + ((end - start) >> 1);
int left = doMergeSmallSum(array, help, start, mid);
int right = doMergeSmallSum(array, help, mid, end);
return left + right + doMerge(array, help, start, mid, end);
}
static int doMerge(int[] array, int[] help, int start, int mid, int end) {
int i = start;
int j = mid;
int k = start;
int sum = 0;
while (i < mid && j < end) {
if (array[i] < array[j]) {
int t = array[i++];
help[k++] = t;
sum += t * (end - j);
} else {
help[k++] = array[j++];
}
}
while (i < mid) {
help[k++] = array[i++];
}
while (j < end) {
help[k++] = array[j++];
}
for (k = start; k < end; k++) {
array[k] = help[k];
}
return sum;
}
}
1 | public class SmallSum { |
求数组中的降序对
例如:
[3, 1, 7, 0, 2]
中的降序对有(3, 1)
、(3, 0)
、(3, 2)
、(1, 0)
、(7, 0)
、(7, 2)
。
即求数组中每个数右边有多少个数比它小,就有多少个降序对。
- Rust 实现
1 |
|