室友1把王者的时间写出了快速排序?(python实现)

前言

"欢迎来到王者荣耀,敌军还有5秒钟达到战场!请做好准备!"

战争的号角已吹响!

本次我方上场的英雄有:小鲁班,诸葛亮,廉颇,韩信,后羿。

还没走出泉水,机智的诸葛亮就率先提出作战策略:游戏可以输,姿势一定要帅!看咱现在这站位,高高低低,乘次不齐,一点排面都没有!

 韩信也马上补充道:“没错!你看这个廉颇,又矮又胖,他还站在C位,你说这像话吗???”

(此时,站在一旁的小鲁班悄悄地想旁边挪了一下)

憨厚的廉颇:我 我。。。

诸葛亮扶了扶眼镜框马上补充道:在座的各位,有没有觉得自己数学好一点的?

(全场寂静了一分钟。。。)

诸葛亮清了清嗓子,再次扶了扶眼镜框,说道:我也当了几十年的数学老师了,黄金分割率就是我提出来的,要不我提个意见怎么样?

(寂静了片刻。。。)

站在一旁的后羿默默地支了一声:也行吧!其他人也一一应和:可以。。。

于是诸葛亮马上又补充道:以我为基准,比我矮的站在我的左边,比我高的站在我的右边。

话音刚落:廉颇就默默地走到了小鲁班的右边,韩信和后羿依次站在了诸葛亮的右边,诸葛亮站到了C位!

现在的站位如下:

 

调皮的小鲁班称赞道:喔!诸葛亮哥哥真厉害,咱们现在不仅是排面杠杆滴!这阵容路线也到位!我和廉颇爷爷个子比较矮,但我的输出高,而廉颇爷爷抗伤能力强,所以我们适合走发育路;而后羿大叔腿子长,输出也还不错,走对抗路也还不错;韩信哥哥更是走位灵活,适合打野发育抓人;诸葛亮哥哥神机妙算,法术高强,走中路再适合不过啦!

韩信也忍不住鼓起了掌声:看你小子个儿不高,脑子还挺灵活的,这波分析杠杆滴!

言归正传

看到诸葛亮的作战策略,不经让我浮想联翩,此情此景似乎在哪里见过?

咦?

这不正是快速排序的核心思想吗?

思路

# 思路  每次排序时,取一个参考元素mid_val,将小于mid_val的元素放到它的左边,将大于mid_val的元素放到它的右边

之后,再分别对在mid_val两边的元素分别进行如上操作

结束条件:分组后的元素个数小于等于1 

快速排序

如果理解了上面的内容,那么你就已经拿下一血了!!

 思路简化

def quick_sort(li, left, right):
    if left < right:  # 至少两个元素
        mid = partition(li, left, right) #原子操作 每次操作后[left,right]区间内的元素,mid左边的都比mid小;mid右边的都比mid大
        quick_sort(li, left, mid - 1)  # 对mid左边的进行排序
        quick_sort(li, mid + 1, right)  # 对mid右边的进行排序

将策略分为3步走:

  1. 输入区间,得出mid值
  2. 操作mid左边的值
  3. 操作mid右边的值

这样思路就清晰了很多!double kill!

 原子操作

最后就是解决这个原子操作的问题了!

列出原子操作的核心功能:

  1. 输入区间
  2. 排序区间
  3. 返回mid

所以来实现一下吧!

def partition(li, left, right):
    mid_val = li[left]

    while left < right:  # 只要左指针不等于右指针循环就没有结束
        while left < right and li[right] >= mid_val:
            right -= 1
        li[left] = li[right]
        while left < right and li[left] <= mid_val:
            left += 1
        li[right] = li[left]

    li[left] = mid_val
    return left

Q:外层循环的条件是left<right,为什么内层循环还需要加这个条件?

A:因为内层的循环,left的一直是不减的,right的值是一直不增的,所以两者可能会相遇!

手动复现一下这个过程!

 初始列表:[3,1,4,2,5]

经过一轮的原子操作后,得到mid=2,在mid左边的都小于mid,在mid右边的都大于mid!

符合预期结果!triple kill!

完整代码

import sys
sys.setrecursionlimit(1000000)  # 设置递归深度
def partition(li, left, right):
    mid_val = li[left]

    while left < right:  # 只要左指针不等于右指针循环就没有结束
        while left < right and li[right] >= mid_val:
            right -= 1
        li[left] = li[right]

        while left < right and li[left] <= mid_val:
            left += 1
        li[right] = li[left]

    li[left] = mid_val
    return left


def quick_sort(li, left, right):
    if left < right:  # 至少两个元素
        mid = partition(li, left, right) #原子操作 每次操作后[left,right]区间内的元素,mid左边的都比mid小;mid右边的都比mid大
        quick_sort(li, left, mid - 1)  # 对mid左边的进行排序
        quick_sort(li, mid + 1, right)  # 对mid右边的进行排序

测试

跑了10w条数据,耗时不到1秒,这效率也是杠杆滴!

结束

 突然寝室里整齐的一声:“victory!

诸葛亮:咦?游戏结束了吗?我还没杀够呢哈哈哈哈

不过快排到时学废了哈哈哈

同步更新于个人博客系统:室友1把王者的时间写出了快速排序?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值