算法题-螺丝与螺母匹配 - Python

螺丝与螺母匹配

问题描述:

给你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++代码,但是参考链接找不到了,抱歉。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值