leetcode 专题:排序 python 版(持续更新中)

目录

常见的排序算法:

1. 冒泡排序

2. 选择排序

3. 插入排序

4. 桶排序

5. 快速排序

6. 归并排序

7. 堆排序

Leetcode

242 有效的字母异位词

349 两个数组的交集

350 两个数组的交集 ||

922 按奇偶排序数组 ||

976 三角形的最大周长


目录

常见的排序算法:

1. 冒泡排序

2. 选择排序

3. 插入排序

4. 桶排序

5. 快速排序

6. 归并排序

7. 堆排序

Leetcode

242 有效的字母异位词

349 两个数组的交集


写在最前面:

python有自带的排序函数,sort和sorted,非常方便,除特殊情况,直接用

常见的排序算法:

1. 冒泡排序

先从数组中找到最大值(或最小值)并放到数组最左端(或最右端),然后在剩下的数字中找到次大值(或次小值),以此类推,直到数组有序排列。

时间复杂度:O(n^2)

def BubbleSort(array):
    length = len(array)
    for i in range(length):
        for j in range(length-i-1):
            if array[j] > array[j+1]:
                array[j], array[j+1] = array[j+1], array[j]
    return array

2. 选择排序

假设长度为n的数组arr,要按照从小到大排序,那么先从n个数字中找到最小值min1,如果最小值min1的位置不在数组的最左端(也就是min1不等于arr[0]),则将最小值min1和arr[0]交换,接着在剩下的n-1个数字中找到最小值min2,如果最小值min2不等于arr[1],则交换这两个数字,依次类推,直到数组arr有序排列。

时间复杂度:O(n^2)

def SelectionSort(array):
    length = len(array)
    for i in range(length):
        min_index = array.index(min(array[i:]))
        if min_index != i:
            array[i], array[min_index] = array[min_index], array[i]      
    return array

3. 插入排序

插入排序的基本思想就是将无序序列插入到有序序列中。

时间复杂度:O(n^2)

def InsertSort(array):
    length = len(array)
    for i in range(1, length):
        if array[i] < array[i-1]:
            for j in range(i, 0, -1):
                if array[j]<array[j-1]:
                    array[j], array[j-1] = array[j-1], array[j]
    return array

4. 桶排序

桶排序的思路:首先找到数组中的最大值,然后新建一个数组,bucket 此数组的长度是数组最大值+1,找到最大值后,开始遍历原数组,把原数组的数据加入bucket的下表中,bucket[i],每当有1个i bucket[i]的值就加一, 然后已经装入桶后, 遍历桶。

时间复杂度:O(n)

def BucketSort(array):
    length = len(array)
    max_n = max(array)
    bucket = [0 for _ in range(max_n+1)]
    for i in range(length):
        bucket[array[i]] += 1
    start = 0
    for j in range(max_n+1):
        if bucket[j]!=0:
            array[start] = j
            start += 1
    return array

5. 快速排序

快排的思想:首先任意选取一个数据作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。

时间复杂度:O(lNogN)

空间复杂度:O(logN)

def QuickSort(array, start, end):
    if start < end:
        index = Partition(array, start, end)
        QuickSort(array, start, index-1)
        QuickSort(array, index+1, end)

def Partition(array, start, end):
    print(start, end)
    small = start-1
    base = array[end]
    for i in range(start, end):
        if array[i] < base:
            small += 1
            if small != i:
                array[small], array[i] = array[i], array[small]
    small+=1
    array[small], array[end] = array[end], array[small]
    return small

6. 归并排序

归并排序采用分而治之的原理:

     一、将一个序列从中间位置分成两个序列;

     二、在将这两个子序列按照第一步继续二分下去;

     三、直到所有子序列的长度都为1,也就是不可以再二分截止。这时候再两两合并成一个有序序列即可。

时间复杂度:O(lNogN)

空间复杂度:O(N)

def MergeSort(array):
    length = len(array)
    if length<=1:
        return array
    middle = length//2
    left = MergeSort(array[:middle])
    right = MergeSort(array[middle:])
    return Merge(left, right)

def Merge(left, right):
    result = []
    i=j=0
    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            result.append(left[i])
            i+=1
        else:
            result.append(right[j])
            j+=1
    result += left[i:]
    result += right[j:]
    return result

7. 堆排序

堆排序(Heap Sort)是利用堆进行排序的方法。其基本思想为:将待排序列构造成一个大顶堆,整个序列的最大值就是堆顶的根结点,将根节点的值和堆数组的末尾元素交换,此时末尾元素就是最大值,然后将剩余的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值,如此反复执行,最终得到一个有序序列。

时间复杂度:O(Nlog(N))

空间复杂度:O(1)

def swap(a, b):  # 将a,b交换
    temp = a
    a = b
    b = temp
    return a,b

def sift_down(array, start, end):
    """
    调整成大顶堆,初始堆时,从下往上;交换堆顶与堆尾后,从上往下调整
    :param array: 列表的引用
    :param start: 父结点
    :param end: 结束的下标
    :return: 无
    """
    while True:
 
        # 当列表第一个是以下标0开始,结点下标为i,左孩子则为2*i+1,右孩子下标则为2*i+2;
        # 若下标以1开始,左孩子则为2*i,右孩子则为2*i+1
        left_child = 2*start + 1  # 左孩子的结点下标
        # 当结点的右孩子存在,且大于结点的左孩子时
        if left_child > end:
            break
 
        if left_child+1 <= end and array[left_child+1] > array[left_child]:
            left_child += 1
        if array[left_child] > array[start]:  # 当左右孩子的最大值大于父结点时,则交换
            array[left_child], array[start] = swap(array[left_child], array[start])
            start = left_child  # 交换之后以交换子结点为根的堆可能不是大顶堆,需重新调整}
        else:  # 若父结点大于左右孩子,则退出循环
            break

        print(">>", array)


def heap_sort(array):  # 堆排序
     # 先初始化大顶堆
    first = len(array)//2 -1  # 最后一个有孩子的节点(//表示取整的意思)
     # 第一个结点的下标为0,很多博客&课本教材是从下标1开始,无所谓吧,你随意
    for i in range(first, -1, -1):  # 从最后一个有孩子的节点开始往上调整
        print(array[i])
        sift_down(array, i, len(array)-1)  # 初始化大顶堆
 
    print("初始化大顶堆结果:", array)
     # 交换堆顶与堆尾
    for head_end in range(len(array)-1, 0, -1):  # start stop step
        array[head_end], array[0] = swap(array[head_end], array[0]) # 交换堆顶与堆尾
        sift_down(array, 0, head_end-1)  # 堆长度减一(head_end-1),再从上往下调整成大顶堆
 

 
if __name__ == "__main__":
    array = [16, 7, 3, 20, 17, 8]
    print(array)
    heap_sort(array)
    print("堆排序最终结果:", array)

Leetcode

242 有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true

示例 2:

输入: s = "rat", t = "car"
输出: false
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        return sorted(s)==sorted(t)

349 两个数组的交集

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2]

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [9,4]

说明:

  • 输出结果中的每个元素一定是唯一的。
  • 我们可以不考虑输出结果的顺序。

 

class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        if not nums1 or not nums2:
            return []
        nums1.sort()
        nums2.sort()
        len1 = len(nums1)
        len2 = len(nums2)
        result = []
        while nums1 and nums2:
            if nums1[0] == nums2[0]:
                if not nums1[0] in result: 
                    result.append(nums1[0])
                nums1.pop(0)
                nums2.pop(0)
            elif nums1[0]>nums2[0]:
                nums2.pop(0)
            elif nums1[0] < nums2[0]:
                nums1.pop(0)
        return result
                
                    

350 两个数组的交集 ||

给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]

示例 2:

输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]

说明:

  • 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
  • 我们可以不考虑输出结果的顺序。

进阶:

  • 如果给定的数组已经排好序呢?你将如何优化你的算法?
  • 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
  • 如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        nums1.sort()
        nums2.sort()
        result = []
        if not nums1 or not nums2:
            return []
        len1 = len(nums1)
        len2 = len(nums2)
        while nums1 and nums2:
            if nums1[0] == nums2[0]:
                result.append(nums1[0])
                nums1.pop(0)
                nums2.pop(0)
            elif nums1[0] > nums2[0]:
                nums2.pop(0)
            elif nums1[0] < nums2[0]:
                nums1.pop(0)
        return result
        

 

922 按奇偶排序数组 ||

给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。

对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。

你可以返回任何满足上述条件的数组作为答案。

 

示例:

输入:[4,2,5,7]
输出:[4,5,2,7]
解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。

 

提示:

  1. 2 <= A.length <= 20000
  2. A.length % 2 == 0
  3. 0 <= A[i] <= 1000

思路: 直接遍历

class Solution:
    def sortArrayByParityII(self, A: List[int]) -> List[int]:
        if not A:
            return []
        odd = 1
        even = 0
        length = len(A)
        result = [None for _ in range(length)]
        
        for i in range(length):
            if A[i] & 1 == 0:
                result[even] = A[i]
                even += 2 
                
            else:
                result[odd] = A[i]
                odd += 2
        return result
        

976 三角形的最大周长

给定由一些正数(代表长度)组成的数组 A,返回由其中三个长度组成的、面积不为零的三角形的最大周长。

如果不能形成任何面积不为零的三角形,返回 0

 

示例 1:

输入:[2,1,2]
输出:5

示例 2:

输入:[1,2,1]
输出:0

示例 3:

输入:[3,2,3,4]
输出:10

示例 4:

输入:[3,6,2,3]
输出:8

 

提示:

  1. 3 <= A.length <= 10000
  2. 1 <= A[i] <= 10^6、

思路:排序检查后三个数

class Solution:
    def largestPerimeter(self, A: List[int]) -> int:
        A.sort()
        length = len(A)
        if length<3:
            return 0
        for i in range(length-1, 1,-1):
            if A[i-1] + A[i-2] > A[i]:
                return A[i-1]+A[i-2]+A[i]
        return 0

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值