-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path912-SortAnArray.go
More file actions
126 lines (115 loc) · 4.22 KB
/
912-SortAnArray.go
File metadata and controls
126 lines (115 loc) · 4.22 KB
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
// 912. Sort an Array
// Given an array of integers nums, sort the array in ascending order and return it.
// You must solve the problem without using any built-in functions in O(nlog(n)) time complexity and with the smallest space complexity possible.
// Example 1:
// Input: nums = [5,2,3,1]
// Output: [1,2,3,5]
// Explanation: After sorting the array, the positions of some numbers are not changed (for example, 2 and 3), while the positions of other numbers are changed (for example, 1 and 5).
// Example 2:
// Input: nums = [5,1,1,2,0,0]
// Output: [0,0,1,1,2,5]
// Explanation: Note that the values of nums are not necessairly unique.
// Constraints:
// 1 <= nums.length <= 5 * 10^4
// -5 * 10^4 <= nums[i] <= 5 * 10^4
import "fmt"
import "math"
func sortArray(nums []int) []int {
return radixSort(nums)
}
func radixSort(nums []int) []int {
abs := func(x int) int { if x < 0 { return -x; }; return x; }
digitCount := func (num int) int {
if num == 0 {
return 1
}
// floor(log10(num)) + 1
// 234 => floor(log10(234)) = 2 + 1
return int(math.Floor(math.Log10(float64(abs(num))))) + 1;
}
reverse := func (nums []int) {
length := len(nums)
for i := 0; i < length / 2; i++ {
nums[i], nums[length - i - 1] = nums[length - i - 1], nums[i]
}
}
getFromBuckets := func(digitBuckets [][]int) []int {
nums := make([]int, 0)
for i := range digitBuckets {
nums = append(nums, digitBuckets[i]...)
}
return nums
}
getDigit := func (num, place int) int {
// (num / 10^place) % 10
// 234, position 1 => 234 / 10^1 => 23 % 10 => 3
return int(math.Floor(float64(abs(num)) / math.Pow(10, float64(place)))) % 10;
}
maxNumber := func (nums []int) int {
res := math.MinInt64
for _, num := range nums {
if res < abs(num) { // !number can be negative
res = abs(num)
}
}
return res
}
maxDigitCount := digitCount(maxNumber(nums)) // how many digits has the longest number
for k := 0; k < maxDigitCount; k++ { // put into the buckets according to the digit at k-th position
digitBuckets := make([][]int, 10)
for i := 0; i < len(nums); i++ {
digitAtKposition := getDigit(nums[i], k)
digitBuckets[digitAtKposition] = append(digitBuckets[digitAtKposition], nums[i])
}
// get from the buckets
nums = getFromBuckets(digitBuckets)
}
signBuckets := make([][]int, 2) // sort negative numbers, we can treat a sign as another bucket
for i := 0; i < len(nums); i++ {
if nums[i] < 0 {
signBuckets[0] = append(signBuckets[0], nums[i])
} else {
signBuckets[1] = append(signBuckets[1], nums[i])
}
}
reverse(signBuckets[0]) // reverse array with negative numbers
nums = getFromBuckets(signBuckets)
return nums
}
func sortArray1(nums []int) []int {
if len(nums) == 0{
return nums
}
mn, mx := nums[0], nums[0]
for _, v := range nums { // 找出最大值 & 最小值
if v < mn { mn = v; }
if v > mx { mx = v; }
}
count := make([]int, mx - mn + 1) // 创建 mx - mn + 1 个桶
for _, num := range nums{
count[num - mn]++
}
res, index := make([]int, len(nums)), 0
for i, cnt := range count {
for j := 0; j < cnt; j++ { // 出现几个就循环几个出来
res[index] = i + mn
index++
}
}
return res
}
func main() {
// Example 1:
// Input: nums = [5,2,3,1]
// Output: [1,2,3,5]
// Explanation: After sorting the array, the positions of some numbers are not changed (for example, 2 and 3), while the positions of other numbers are changed (for example, 1 and 5).
fmt.Println(sortArray([]int{5,2,3,1})) // [1,2,3,5]
// Example 2:
// Input: nums = [5,1,1,2,0,0]
// Output: [0,0,1,1,2,5]
// Explanation: Note that the values of nums are not necessairly unique.
fmt.Println(sortArray([]int{5,1,1,2,0,0})) // [0,0,1,1,2,5]
fmt.Println(sortArray1([]int{5,2,3,1})) // [1,2,3,5]
fmt.Println(sortArray1([]int{5,1,1,2,0,0})) // [0,0,1,1,2,5]
}