是能百度到这个问题的,但是他们的分析越看越迷糊,我现在也没理解,所以在这里写一个具体的分析。
螺钉和螺母排序问题:现给定一堆螺钉和螺母(螺母和螺钉一对一唯一配对,即不存在相同大小的螺钉或螺母),现需要对螺母和螺钉按尺寸的大小排序。但是要求是不能直接根据螺钉或螺母尺寸大小进行排序,仅能通过给定的一个match函数比较大小(match()方法比较螺母和螺钉的尺寸大小,0表示两者匹配,1表示螺母尺寸大于螺钉尺寸,-1表示螺母尺寸小于螺钉尺寸)。
根据不能直接根据螺钉或螺母尺寸大小进行排序 ,所以能猜到有快排的意思,使用一个基准A,将序列分为比A大、比A小、等于A三部分。
首先从螺母(Nut)中随机取一个数(默认第一个元素),以该数作为螺钉(Screw)的基数去进行一次快速排序:
① 假设该基准元素位于最后一位,i j 同时从首个元素出发,j 从第一个元素开始向后寻找:
(1) 当 j 位置的元素小于基准元素,则 i j 的元素交换,i 往后移动一位,j 继续往后寻找;
(2) 当 j 位置的元素等于基准元素,则 j 所在的与最后一位元素进行交换,j 从当前位置继续往后寻找;
(3) 当 j 位置的元素大于基准元素,则 j 继续往后寻找;
② 直到 j == right 时,交换 i j 所在的元素,返回 i ,一次排序结束
从螺钉(Screw)中选择进行一次排序返回的基准元素,作为螺母(Nut)的基准元素去对螺母进行一次快速排序:
① 假设该基准元素位于最后一位,i j 同时从首个元素出发,j 从第一个元素开始向后寻找:
(1) 当 j 位置的元素小于基准元素,则 i j 的元素交换,i 往后移动一位,j 继续往后寻找;
(2) 当 j 位置的元素等于基准元素,则 j 所在的与最后一位元素进行交换,j 从当前位置继续往后寻找;
(3) 当 j 位置的元素大于基准元素,则 j 继续往后寻找;
② 直到 j == right 时,交换 i j 所在的元素,返回 i ,一次排序结束。
package suanfa
import (
"fmt"
"testing"
)
func TestMatch(t *testing.T) {
sortNutsAndBolts([]int{5, 1, 2, 4, 3}, []int{1, 4, 3, 5, 2})
}
func sortNutsAndBolts(nuts []int, bolts []int) {
quickSort(nuts, bolts, 0, len(nuts)-1)
fmt.Println(nuts, bolts)
}
func quickSort(nuts []int, bolts []int, l, r int) {
if l >= r {
return
}
std := partition(bolts, l, r, nuts[l])
partition(nuts, l, r, bolts[std])
quickSort(nuts, bolts, l, std-1)
quickSort(nuts, bolts, std+1, r)
}
func partition(nums []int, l, r, std int) int {
if l >= r {
return l
}
// i和j都是第一个元素
i, j := l, l
for j < r {
if nums[j] < std {
// j位置的元素小于基准元素,i j 交换,i向后移动一位,j继续寻找
nums[i], nums[j] = nums[j], nums[i]
i++
} else if nums[j] == std {
// 与std相等,与最后一个元素交换,继续下一个元素比较
nums[j], nums[r] = nums[r], nums[j]
continue
}
j++
}
nums[i], nums[j] = nums[j], nums[i]
return i
}
时间复杂度是o(nlogn)
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 18 天,点击查看活动详情