Leecode 101刷题笔记之第五章:和你一起你轻松刷题(Python)

简介: 这篇文章是关于LeetCode第101章的刷题笔记,涵盖了多种排序算法的Python实现和两个中等难度的编程练习题的解法。

冒泡排序

思想
相邻的元素两两比较,较大的数下沉,较小的数冒起来,这样一趟比较下来,最大(小)值就会排列在一端。整个过程如同气泡冒起,因此被称作冒泡排序。

import random
from visual import visualizer

def maopaoSort(arr):
    return maopao(arr,len(arr)-1)

def maopao(num,n):
    for i in range(n):
        #对前一个的数据与后一个的数据进行比较
        for j in range(n):
            if num[j+1]<num[j]:
                visualizer.draw_bars(num, j, j + 1, len(num))
                num[j],num[j+1]=num[j+1],num[j]
    return num

if __name__ == '__main__':
    date = list(range(1, 101))
    random.shuffle(date)
    visualizer.t.bgcolor('black')
    maopaoSort(date)
    visualizer.t.done()
AI 代码解读

快速排序

思想
通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可以对这两部分记录继续进行排序,以达到整个系列有序。
具体代码

import random
from visual import visualizer

def quicksort(nums):
    quicksorthelper(nums,0,len(nums)-1)
    return nums

def quicksorthelper(nums,startidex,rightidex):
    # 如果列表中只有一个元素或者不存在的话
    if startidex>=rightidex:return
    # 找出第一个元素为初始值
    pivotidex=startidex
    privovalue=nums[pivotidex]
    # 以第二个元素为左指针
    left=startidex+1
    # 以第最后元素为右指针
    right=rightidex
    while left<=right:
        # 如果左指针指向的元素大于初始值大于右指针的元素,则说明左指针的值应该和右指针进行替换
        if nums[left]>privovalue>nums[right]:
            visualizer.draw_bars(nums, left, right, len(nums))
            nums[left],nums[right]=nums[right],nums[left]
        # 如果左指针的元素小于等于初始值,则不需要替换,只需要将左指针往右移动一位
        if nums[left]<=privovalue:
            left+=1
        # 如果右指针的元素大于等于初始值,则不需要替换,只需要将右指针往左移动一位
        if nums[right]>=privovalue:
            right-=1
    # 调换初始指针和右指针的元素位置,完成一次快速排序
    nums[right],nums[pivotidex]=nums[pivotidex],nums[right]
    visualizer.draw_bars(nums, pivotidex, right, len(nums))
    # 每一次递归操作都需要去额外的开辟存储空间,为了尽可能降低空间复杂度
    # 需要先判断左右列表的长短,先对短的进行快速排序,在对长的进行快速排序即可。
    leftlength=right-startidex
    rightlength=rightidex-right
    if leftlength<rightlength:
        quicksorthelper(nums,startidex,right-1)
        quicksorthelper(nums,right+1,rightidex)
    else:
        quicksorthelper(nums,right+1,rightidex)
        quicksorthelper(nums,startidex,right-1)

if __name__ == '__main__':
    date = list(range(1, 101))
    random.shuffle(date)
    visualizer.t.bgcolor('black')
    quicksort(date)
    visualizer.t.done()
AI 代码解读

归并排序

思想
并指将两个或两个以上的有序数表合并成一个新的有序表
步骤

  1. 将序列中带排序数字分为若干组,每个数字分为一组
  2. 将若干个组两两合并,保证合并后的组是有序的
  3. 重复第二步操作直到只剩下一组,排序完成
import random
from visual import visualizer
def merge(nums,left,mid,right):
    new_nums=[]
    l,r=left,mid+1
    while l<=mid and r<=right:
        if nums[l]<nums[r]:
            new_nums.append(nums[l])
            visualizer.draw_bars(nums,l,r,len(nums))
            l+=1
        else:
            new_nums.append(nums[r])
            visualizer.draw_bars(nums,l,r,len(nums))
            r+=1
    while l<=mid:
        new_nums.append(nums[l])
        visualizer.draw_bars(nums, l, r, len(nums))
        l+=1
    while r<=right:
        new_nums.append(nums[r])
        visualizer.draw_bars(nums, l, r, len(nums))
        r+=1
    nums[left:right+1]=new_nums

def merge_sort(nums,left,right):
    if left<right:
        mid=(left+right)//2
        merge_sort(nums,left,mid)
        merge_sort(nums,mid+1,right)
        merge(nums,left,mid,right)
        visualizer.draw_bars(nums, -1, -1, len(nums))

def run(nums):
    l,r=0,len(nums)-1
    return merge_sort(nums,l,r)

if __name__ == '__main__':
    date=list(range(1,101))
    random.shuffle(date)
    visualizer.t.bgcolor('black')
    run(date)
    visualizer.t.done()
AI 代码解读

插入排序

思想
将给定元素分为两组,开始第一个元素分为一组,后面的元素分为一组,然后通过不断遍历后面的元素不断插入到前面合适的位置。

# 原理:将给定元素分为两组,开始第一个元素分为一组,后面的元素分为一组,然后通过不断遍历后面的元素不断插入到前面合适的位置
import random
from visual import visualizer
# 0(n^2)Time | O(1) Space
# stable
def insert_arr(a):
    for i in range(len(a)):
        j=i
        while j>0 and a[j]<a[j-1]:
            visualizer.draw_bars(a,j,j-1,len(a))
            a[j],a[j-1]=a[j-1],a[j]
            j-=1
    return a

if __name__ == '__main__':
    date=list(range(1,101))
    random.shuffle(date)
    visualizer.t.bgcolor('black')
    insert_arr(date)
    visualizer.t.done()
AI 代码解读

桶排序

思想
将阵列分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递回方式继续使用桶排序进行排序。

import random

def Tongsort(x):
    # 找到数组的最大值和最小值
    # 方法1
    maxvalue,minvalue=x[0],x[0]
    for i in range(1,len(x)):
        if x[i]>maxvalue:
            maxvalue=x[i]
        if x[i]<minvalue:
            minvalue=x[i]
    # 方法2
    # maxvalue,minvalue=max(x),min(x)

    # 计算桶的数量
    bucketnum=(maxvalue-minvalue)//3+1
    bucket=[[]for i in range(bucketnum)]
    # 根据数值对桶进行划分
    for i in x:
        bucket[i//3].append(i)

    # 针对每一个桶使用快速排序
    for b in bucket:
        quicksorthelper(b,0,len(b)-1)
    x.clear()
    for i in bucket:
        x.extend(i)
    return x

def quicksorthelper(nums,startidex,rightidex):
    # 如果列表中只有一个元素或者不存在的话
    if startidex>=rightidex:return
    # 找出第一个元素为初始值
    pivotidex=startidex
    privovalue=nums[pivotidex]
    # 以第二个元素为左指针
    left=startidex+1
    # 以第最后元素为右指针
    right=rightidex
    while left<=right:
        # 如果左指针指向的元素大于初始值大于右指针的元素,则说明左指针的值应该和右指针进行替换
        if nums[left]>privovalue>nums[right]:
            nums[left],nums[right]=nums[right],nums[left]
        # 如果左指针的元素小于等于初始值,则不需要替换,只需要将左指针往右移动一位
        if nums[left]<=privovalue:
            left+=1
        # 如果右指针的元素大于等于初始值,则不需要替换,只需要将右指针往左移动一位
        if nums[right]>=privovalue:
            right-=1
    # 调换初始指针和右指针的元素位置,完成一次快速排序
    nums[right],nums[pivotidex]=nums[pivotidex],nums[right]
    # 每一次递归操作都需要去额外的开辟存储空间,为了尽可能降低空间复杂度
    # 需要先判断左右列表的长短,先对短的进行快速排序,在对长的进行快速排序即可。
    leftlength=right-startidex
    rightlength=rightidex-right
    if leftlength<rightlength:
        quicksorthelper(nums,startidex,right-1)
        quicksorthelper(nums,right+1,rightidex)
    else:
        quicksorthelper(nums,right+1,rightidex)
        quicksorthelper(nums,startidex,right-1)

if __name__ == '__main__':
    date=list(range(1,11))
    random.shuffle(date)
    b=Tongsort(date)
    print(b)
AI 代码解读

选择排序

思想
第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,继续放在起始位置知道未排序元素个数为0。

#基本原理:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,继续放在起始位置知道未排序元素个数为0
import random
from visual import visualizer
# 时间复杂度
# 空间复杂度
# 是否稳定

def Selectsort(a):
    # 将每一轮的最小值的索引找出来,并放入序列的起始位置
    for i in range(len(a)-1):
        # key
        start_idex=i
        for j in range(i+1,len(a)):
            # 为了找更小的值
            visualizer.draw_bars(a, i, j, len(a))
            if a[start_idex]>a[j]:
                start_idex=j
        # start_idex为我们选出来的最小值索引,i为每一轮的初始值,就进行相应替换即可
        a[start_idex],a[i]=a[i],a[start_idex]
        visualizer.draw_bars(a, i, start_idex, len(a))
    return a

if __name__ == '__main__':
    date=list(range(1,20))
    random.shuffle(date)
    visualizer.t.bgcolor('black')
    Selectsort(date)
    visualizer.t.done()
AI 代码解读

练习-基础难度

451. Sort Characters By Frequency (Medium)

桶排序的变形题。
题目描述
给定一个字符串 s ,根据字符出现的 频率 对其进行 降序排序 。一个字符出现的 频率 是它出现在字符串中的次数。

返回 已排序的字符串 。如果有多个答案,返回其中任何一个。
输入输出样例

输入: s = "tree"
输出: "eert"
解释: 'e'出现两次,'r'和't'都只出现一次。
因此'e'必须出现在'r'和't'之前。此外,"eetr"也是一个有效的答案。
AI 代码解读

具体代码

"""
解题1:通过桶排序来做
执行用时:56 ms, 在所有 Python 提交中击败了35.11%的用户
内存消耗:28.6 MB, 在所有 Python 提交中击败了5.34%的用户
"""
def frequencySort(s):
    # 统计各元素的频率
    dic=dict()
    for i in s:
        dic[i]=dic.get(i,0)+1
    # 设置桶的数量
    buckets=[[]for _ in range(len(s)+1)]
    for  key,value in dic.items():
        buckets[value].append(key)
    res=""
    for j in range(len(s),-1,-1):
        if buckets[j]:
            if len(buckets[j])!=1:
                for k in buckets[j]:
                    res+=''.join(k*j)
            else:
                res += ''.join(buckets[j] * j)
    return res

"""
解题2:直接调用Counter进行计算
执行用时:44 ms, 在所有 Python 提交中击败了60.44%的用户
内存消耗:14.9 MB, 在所有 Python 提交中击败了76.00%的用户
"""
from collections import Counter
def frequencySort1(s):
    a=Counter(s).most_common()
    res=''
    for k,v in a:
        res+=''.join(k*v)
    return res

if __name__ == '__main__':
    s = "tree"
    a=frequencySort1(s)
    print(a)
AI 代码解读

练习-进阶难度

75. Sort Colors (Medium)

很经典的荷兰国旗问题,考察如何对三个重复且打乱的值进行排序。
题目描述
给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
必须在不使用库的sort函数的情况下解决这个问题。
输入输出样例

输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]
AI 代码解读

具体代码

"""
解题1:
执行用时: 12ms, 在所有 Python 提交中击败了94.81的用户
内存消耗: 12.8MB, 在所有 Python 提交中击败了94.34的用户
"""

def sortColors(nums):
    sum_0,sum_1=0,0
    for num in nums:
        if num==0:
            sum_0+=1
        elif num==1:
            sum_1+=1

    for i in range(len(nums)):
        if i<sum_0:
            nums[i]=0
        elif i<(sum_0+sum_1):
            nums[i]=1
        else:
            nums[i]=2
    return nums

if __name__ == '__main__':
    nums = [2, 0, 2, 1, 1, 0]
    result = sortColors(nums)
    print(result)
AI 代码解读
目录
打赏
0
3
3
0
86
分享
相关文章
|
6月前
|
Leecode 101刷题笔记之第四章:和你一起你轻松刷题(Python)
这篇博客是关于LeetCode上使用Python语言解决二分查找问题的刷题笔记,涵盖了从基础到进阶难度的多个题目及其解法。
55 0
|
6月前
|
Leecode 101刷题笔记之第三章:和你一起你轻松刷题(Python)
本文是关于LeetCode算法题的刷题笔记,主要介绍了使用双指针技术解决的一系列算法问题,包括Two Sum II、Merge Sorted Array、Linked List Cycle II等,并提供了详细的题解和Python代码实现。
52 0
|
6月前
|
Leecode 101刷题笔记之第二章:和你一起你轻松刷题(Python)
本文是关于LeetCode 101刷题笔记的第二章,主要介绍了使用Python解决贪心算法题目的方法和实例。
45 0
Python 高级编程与实战:深入理解性能优化与调试技巧
本文深入探讨了Python的性能优化与调试技巧,涵盖profiling、caching、Cython等优化工具,以及pdb、logging、assert等调试方法。通过实战项目,如优化斐波那契数列计算和调试Web应用,帮助读者掌握这些技术,提升编程效率。附有进一步学习资源,助力读者深入学习。
[oeasy]python081_ai编程最佳实践_ai辅助编程_提出要求_解决问题
本文介绍了如何利用AI辅助编程解决实际问题,以猫屎咖啡的购买为例,逐步实现将购买斤数换算成人民币金额的功能。文章强调了与AI协作时的三个要点:1) 去除无关信息,聚焦目标;2) 将复杂任务拆解为小步骤,逐步完成;3) 巩固已有成果后再推进。最终代码实现了输入验证、单位转换和价格计算,并保留两位小数。总结指出,在AI时代,人类负责明确目标、拆分任务和确认结果,AI则负责生成代码、解释含义和提供优化建议,编程不会被取代,而是会更广泛地融入各领域。
72 28
Python 高级编程与实战:深入理解数据科学与机器学习
本文深入探讨了Python在数据科学与机器学习中的应用,介绍了pandas、numpy、matplotlib等数据科学工具,以及scikit-learn、tensorflow、keras等机器学习库。通过实战项目,如数据可视化和鸢尾花数据集分类,帮助读者掌握这些技术。最后提供了进一步学习资源,助力提升Python编程技能。
|
1月前
|
[oeasy]python074_ai辅助编程_水果程序_fruits_apple_banana_加法_python之禅
本文回顾了从模块导入变量和函数的方法,并通过一个求和程序实例,讲解了Python中输入处理、类型转换及异常处理的应用。重点分析了“明了胜于晦涩”(Explicit is better than implicit)的Python之禅理念,强调代码应清晰明确。最后总结了加法运算程序的实现过程,并预告后续内容将深入探讨变量类型的隐式与显式问题。附有相关资源链接供进一步学习。
36 4
Python 高级编程与实战:深入理解设计模式与软件架构
本文深入探讨了Python中的设计模式与软件架构,涵盖单例、工厂、观察者模式及MVC、微服务架构,并通过实战项目如插件系统和Web应用帮助读者掌握这些技术。文章提供了代码示例,便于理解和实践。最后推荐了进一步学习的资源,助力提升Python编程技能。
Python 高级编程与实战:深入理解性能优化与调试技巧
本文深入探讨了Python的性能优化和调试技巧,涵盖使用内置函数、列表推导式、生成器、`cProfile`、`numpy`等优化手段,以及`print`、`assert`、`pdb`和`logging`等调试方法。通过实战项目如优化排序算法和日志记录的Web爬虫,帮助你编写高效稳定的Python程序。
在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境
以上内容是一个简单的实现在Java后端中通过DockerClient操作Docker生成python环境并执行代码,最后销毁的案例全过程,也是实现一个简单的在线编程后端API的完整流程,你可以在此基础上添加额外的辅助功能,比如上传文件、编辑文件、查阅文件、自定义安装等功能。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
在线编程实现!如何在Java后端通过DockerClient操作Docker生成python环境