Introduction Link to heading
Given two arrays arr1
and arr2
, the elements of arr2
are distinct, and all elements in arr2
are also in arr1
.
Sort the elements of arr1
such that the relative ordering of items in arr1
are the same as in arr2
. Elements that don’t appear in arr2
should be placed at the end of arr1
in ascending order.
Example 1:
Input: arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
Output: [2,2,2,1,4,3,3,9,6,7,19]
Constraints:
arr1.length, arr2.length <= 1000
0 <= arr1[i], arr2[i] <= 1000
Each arr2[i] is distinct.
Each arr2[i] is in arr1.
Solution Link to heading
func relativeSortArray(arr1 []int, arr2 []int) []int {
m := make(map[int]int)
for _, v := range arr1 {
m[v]++
}
var out []int
for _, v := range arr2 {
cnt := m[v]
for j := 0; j < cnt; j++ {
out = append(out, v)
}
delete(m, v)
}
var keys []int
for k := range m {
keys = append(keys, k)
}
sort.Ints(keys)
for _, v := range keys {
cnt := m[v]
for j := 0; j < cnt; j++ {
out = append(out, v)
}
}
return out
}
Explanation Link to heading
The simple solution would be to use maps.
Let’s try to use the fact, that values in arrays are in range [0, 1000], therefore, instead of slow hash maps we can end up with arrays, by decreasing complexity of the task to O(n+m+log(n-m))
Solution with arrays Link to heading
func relativeSortArray(arr1 []int, arr2 []int) []int {
dist := make([]int, 1001)
for i, v := range arr2 {
dist[v] = i + 1
}
cnt := make([]int, len(arr2))
var tail []int
for _, v := range arr1 {
i := dist[v] - 1
if i >= 0 {
cnt[i]++
} else {
tail = append(tail, v)
}
}
sort.Ints(tail)
var out []int
for i, c := range cnt {
for j := 0; j < c; j++ {
out = append(out, arr2[i])
}
}
return append(out, tail...)
}
Next step Link to heading
Let’s remove sorting by integers on tail and combine counter in one array. Here it is the best solution:
func relativeSortArray(arr1 []int, arr2 []int) []int {
cache := make([]int, 1001)
for _, n := range arr1 {
cache[n]++
}
var out []int
for _, n := range arr2 {
cnt := cache[n]
for i := 0; i < cnt; i++ {
out = append(out, n)
}
cache[n] = 0
}
for n, cnt := range cache {
for i := 0; i < cnt; i++ {
out = append(out, n)
}
}
return out
}