智力题:螺钉螺母匹配问题

582 阅读3分钟

是能百度到这个问题的,但是他们的分析越看越迷糊,我现在也没理解,所以在这里写一个具体的分析。

螺钉和螺母排序问题:现给定一堆螺钉和螺母(螺母和螺钉一对一唯一配对,即不存在相同大小的螺钉或螺母),现需要对螺母和螺钉按尺寸的大小排序。但是要求是不能直接根据螺钉或螺母尺寸大小进行排序,仅能通过给定的一个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 天,点击查看活动详情

参考

blog.csdn.net/weixin_4435…