问题描述:
给你2
堆大小不同的螺丝
与螺母
,螺丝与螺母是相互匹配
的,但是螺丝与螺丝之间,螺母与螺母之间不能直接对比
,仅仅螺丝与螺母
进行对比,请设计一个分治算法实现。
示例:
输入:nuts = [5, 3, 7, 1, 6],bolts = [1, 7, 6, 3, 5] #
nuts
表示螺母,bolts
表示螺丝或者螺栓
输出:nuts =[1, 3, 5, 6, 7], bolts = [1, 3, 5, 6, 7]
问题分析:
题目有一定难度,但是理解透彻了之后你会发现,其实并不难,这里利用分而治之(快速排序)的思想来解决。具体如何去做,使用递归就可以实现,现在咱们就走一边,第一步:
(1)从nuts
中选一个元素,假设选取的是nuts[0]
,与 bolts
中的所有元素
做比较,找出与其相等的元素bolts[mark]
(最右边那个),同时统计比nuts[0]
小的元素个数count
。
for i in range(l, r + 1):
t = self.cmp(a[l], b[i]) # a中的第一个值(元素)为基准,与b中所有值做比较,用来确定b中与a[0]相等的元素位置mark,和 b 中小于a[0]元素的个数 count
if t == 0: mark = i # a第一个元素和b相等元素, 最终会找到b中的最右边的匹配
elif t == 1: count += 1 # a第一个元素大于b中的元素的个数
(2)根据统计的比nuts[0]
小的元素个数count
,就可以确定当前nuts[0]
的最终位置,同时也就确定了bolts[mark]
的最终位置,进行归位
操作,相当于快速排序中归位
一个元素。
a[l], a[l + count] = a[l + count], a[l] # a 的左半部分分配count个元素
b[mark], b[l + count] = b[l + count], b[mark] # b 的左半部分分出来count个元素
mark = l + count # mark 就是相同的匹配了, mark就是中轴
(3)其他的值都以这个基准为标杆
,小于的放到左区间
,大于的放到右区间
,然后接着递归左右区间,即可完成排序。
Python3实现:
# @Time :2023/08/15
# @Author :Liu
# 分治思想
class Solution:
def cmp(self, a, b): # 比较大小
if a > b: return 1
if a == b: return 0
if a < b: return -1
def quickSort(self, a, b, l, r):
mark, count = 0, 0
for i in range(l, r + 1):
t = self.cmp(a[l], b[i]) # a中的第一个值(元素)为基准,与b中所有值做比较,用来确定b中与a[0]相等的元素位置mark,和 b 中小于a[0]元素的个数 count
if t == 0: mark = i # a第一个元素和b相等元素, 最终会找到b中的最右边的匹配
elif t == 1: count += 1 # a第一个元素大于b中的元素的个数
a[l], a[l + count] = a[l + count], a[l] # a 的左半部分分配count个元素
b[mark], b[l + count] = b[l + count], b[mark] # b 的左半部分分出来count个元素
mark = l + count # mark 就是相同的匹配了, mark就是中轴
i, j = l, r
while i < mark < j: # a 分成两部分
while i < mark and self.cmp(a[i], b[mark]) == -1: # 小于的
i += 1
while j > mark and self.cmp(a[j], b[mark]) == 1: # 大于的
j -= 1
if i < j: # swap
a[i], a[j] = a[j], a[i]
i, j = l, r
while i < mark < j: # b 分成两部分
while i < mark and self.cmp(a[mark], b[i]) == 1:
i += 1
while j > mark and self.cmp(a[mark], b[j]) == -1:
j -= 1
if i < j: # swap
b[i], b[j] = b[j], b[i]
if l < mark: self.quickSort(a, b, l, mark - 1)
if r > mark: self.quickSort(a, b, mark + 1, r)
if __name__ == '__main__':
# 测试用例
nuts = [5, 3, 7, 1, 6]
bolts = [1, 7, 6, 3, 5]
sol = Solution()
sol.quickSort(nuts, bolts, 0, len(nuts) - 1)
print(nuts) # 输出 [1, 3, 5, 6, 7]
print(bolts) # 输出 [1, 3, 5, 6, 7]
声明: 总结学习,有问题或不当之处,可以批评指正哦,谢谢。
参考了一个C++代码,但是参考链接找不到了,抱歉。