Skip to content

Commit ed1312c

Browse files
authored
feat: add CountingSort and doc (doocs#817)
1 parent d84c43d commit ed1312c

File tree

4 files changed

+119
-0
lines changed

4 files changed

+119
-0
lines changed

basic/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- [归并排序](/basic/sorting/MergeSort/README.md)
99
- [快速排序](/basic/sorting/QuickSort/README.md)
1010
- [堆排序](/basic/sorting/HeapSort/README.md)
11+
- [计数排序](/basic/sorting/CountingSort/README.md)
1112

1213
## 查找算法
1314

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package CountingSort
2+
3+
func CountingSort(nums []int, min, max int) {
4+
n := len(nums)
5+
k := max - min + 1
6+
c := make([]int, k)
7+
for _, v := range nums {
8+
c[v-min]++
9+
}
10+
11+
for i := 1; i < k; i++ {
12+
c[i] += c[i-1]
13+
}
14+
15+
r := make([]int, n)
16+
for i := n - 1; i >= 0; i-- {
17+
v := nums[i]
18+
a := c[v]
19+
r[a-1] = v + min
20+
c[v]--
21+
}
22+
23+
for i, v := range r {
24+
nums[i] = v
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
public static void sort(int[] nums, int min, int max) {
2+
int n = nums.length;
3+
int k = max - min + 1;
4+
int[] c = new int[k];
5+
for (int v : nums) {
6+
c[v - min]++;
7+
}
8+
for (int i = 1; i < k; i++) {
9+
c[i] += c[i - 1];
10+
}
11+
int[] r = new int[n];
12+
for (int i = n - 1; i >= 0; i--) {
13+
int v = nums[i];
14+
int a = c[v];
15+
r[a - 1] = v + min;
16+
c[v]--;
17+
}
18+
System.arraycopy(r, 0, nums, 0, n);
19+
}

basic/sorting/CountingSort/README.md

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# 计数排序
2+
3+
计数排序是一个非基于比较的排序算法,是一种空间换时间的算法,是通过元素的值来确定元素的位置, 适用于非负整数的排序(如果负数需要排序,那么需要使所有元素都添加上 `0-min` 之后再减去该值)
4+
5+
算法描述:
6+
- 给定原数组中元素值的范围 `[min, max]`
7+
- 创建一个新数组 `c` ,其长度是 `max-min+1`,其元素默认值都是 `0`
8+
- 遍历原数组中的元素,以原数组中的元素作为 `c` 数组的索引,以原数组中的元素出现次数作为 `c` 数组的元素值。
9+
- 创建结果数组 `r`,起始索引 `i`
10+
- 遍历数组 `c`,找出其中元素大于 `0` 的元素,将其对应的索引作为元素值填充到 `r` 数组中,每处理一次,`c` 中的元素值减 `1`,直到该元素值不大于 `0`,依次处理 `c` 中剩下的元素
11+
12+
## 代码示例
13+
14+
<!-- tabs:start -->
15+
16+
### **Java**
17+
18+
```java
19+
public static void sort(int[] nums, int min, int max) {
20+
int[] c = new int[max - min + 1];
21+
for (int v : nums) {
22+
c[v - min]++;
23+
}
24+
for (int i = 1; i < c.length; i++) {
25+
c[i] += c[i - 1];
26+
}
27+
int[] r = new int[nums.length];
28+
for (int i = nums.length - 1; i >= 0; i--) {
29+
int v = nums[i];
30+
int a = c[v];
31+
r[a - 1] = v + min;
32+
c[v]--;
33+
}
34+
System.arraycopy(r, 0, nums, 0, r.length);
35+
}
36+
```
37+
38+
### **Go**
39+
40+
```go
41+
func CountingSort(nums []int, min, max int) {
42+
n := len(nums)
43+
k := max - min + 1
44+
c := make([]int, k)
45+
for _, v := range nums {
46+
c[v-min]++
47+
}
48+
49+
for i := 1; i < k; i++ {
50+
c[i] += c[i-1]
51+
}
52+
53+
r := make([]int, n)
54+
for i := n - 1; i >= 0; i-- {
55+
v := nums[i]
56+
a := c[v]
57+
r[a-1] = v + min
58+
c[v]--
59+
}
60+
61+
for i, v := range r {
62+
nums[i] = v
63+
}
64+
}
65+
```
66+
67+
<!-- tabs:end -->
68+
69+
## 算法分析
70+
71+
- 时间复杂度 `O(n+k)`, 其中 `n` 为排序数组长度,`k` 为排序数组中数值的取值范围,当 `k < n` 时,时间复杂度为 `O(n)`
72+
- 空间复杂度 `O(n+k)`, 其中 `n` 为排序数组长度,`k` 为排序数组中数值的取值范围,当 `k < n` 时,空间复杂度为 `O(n)`
73+

0 commit comments

Comments
 (0)