首页 > 编程语言 >五. 排序算法

五. 排序算法

时间:2022-12-07 15:06:13浏览次数:59  
标签:return nums int self next 算法 排序 def


1.定义:

1.1 原地排序和非原地排序

def. 原地排序算法使用恒定的的额外空间来产生输出。

原地排序:选择排序,插入排序,希尔排序,快速排序,堆排序。

非原地排序:归并排序,计数排序,基数排序。

1.2 内部排序和外部排序

def. 当所有待排序记录不能被一次载入内存进行处理时,这样的排序就被称为外部排序。外部排序通常应用在待排序记录的数量非常大的时候。

内部排序:其他。

外部排序:归并排序以及它的变体。

1.3 稳定排序和不稳定排序

def. 待排序序列中的相等记录,排序前后位置不变。

稳定排序:​​插入排序​​​,​​基数排序​​​,​​归并排序​​​,​​冒泡排序​​​,​​计数排序​

不稳定排序:​​快速排序​​​,​​希尔排序​​​,​​简单选择排序​​​,​​堆排序​

2.快速排序:分治思想,《算法模板》

def partition(a: list, lo: int, hi: int) -> int:
i = lo + 1; j = hi
v = a[lo]
while True:
# = 防止重复数据
while a[i] <= v and i < hi: i += 1
while a[j] > v and j > lo: j -= 1
if i >= j: break
a[i], a[j] = a[j], a[i]
a[lo], a[j] = a[j], a[lo]
return j

def quickSort(a: list, lo: int, hi: int) -> list:
if lo < hi:
v = partition(a, lo, hi)
quickSort(a, lo, v - 1)
quickSort(a, v + 1, hi)
return a

if __name__ == '__main__':
a = [2,2,2,2,2,2,2,2]
res = quickSort(a, 0, len(a)-1)
print(res)

eg:

​912. 排序数组​

class Solution:
def partition(self, a: list, lo: int, hi: int) -> int:
i = lo + 1; j = hi
v = a[lo]
while True:
while a[i] <= v and i < hi: i += 1
while a[j] > v and j > lo: j -= 1
if i >= j: break
a[i], a[j] = a[j], a[i]
a[lo], a[j] = a[j], a[lo]
return j

def quickSort(self, a: list, lo: int, hi: int) -> list:
if lo < hi:
v = self.partition(a, lo, hi)
self.quickSort(a, lo, v - 1)
self.quickSort(a, v + 1, hi)
return a

def sortArray(self, nums: List[int]) -> List[int]:
return self.quickSort(nums, 0, len(nums)-1)
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:

def partition(nums, lo, hi):
p_idx = random.randint(lo, hi) # 随机选择p
nums[lo], nums[p_idx] = nums[p_idx], nums[lo] # p放置到最左边
p = nums[lo] # 选取最左边为p
l, r = lo, hi # 双指针
while l < r:
while l<r and nums[r] >= p: # 找到右边第一个<p的元素
r -= 1
nums[l] = nums[r] # 并将其移动到l处
while l<r and nums[l] <= p: # 找到左边第一个>p的元素
l += 1
nums[r] = nums[l] # 并将其移动到r处
nums[l] = p # p放置到中间l=r处
return l

def quickSort(nums, lo, hi):
if lo >= hi: return # 递归结束
mid = partition(nums, lo, hi) # 以mid为分割点
quickSort(nums, lo, mid-1) # 递归对mid两侧元素进行排序
quickSort(nums, mid+1, hi)

quickSort(nums, 0, len(nums)-1) # 调用快排函数对nums进行排序
return nums
class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
def helper(nums):
if len(nums) < 2: return nums
p = nums[0]
left = [i for i in nums[1:] if i <= p]
right = [i for i in nums[1:] if i > p]
return helper(left) + [p] + helper(right)
return helper(nums)

​215. 数组中的第K个最大元素​

class Solution:
def sortArray(self, nums: List[int]) -> List[int]:
def helper(nums):
if len(nums) < 2: return nums
key = nums[0]
left = [i for i in nums[1:] if i <= key]
right = [i for i in nums[1:] if i > key]
return helper(left) + [key] + helper(right)
return helper(nums)
def findKthLargest(self, nums: List[int], k: int) -> int:
res = self.sortArray(nums)
return res[-k]

3. 归并排序:两个不同的有序数组归并到第三个数组中,分治思想

def merge(left: list, right: list) -> list:
res = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
res.append(left[i])
i += 1
else:
res.append(right[j])
j += 1
if i == len(left):
res.extend(right[j:])
else:
res.extend(left[i:])
return res

def mergeSort(arr: list) -> list:
if len(arr) <= 1: return arr
mid = len(arr) // 2
left = mergeSort(arr[:mid])
rigit = mergeSort(arr[mid:])
return merge(left, rigit)

eg.

​21. 合并两个有序链表​

​剑指 Offer 25. 合并两个排序的链表​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
head = cur = ListNode(0)
while list1 and list2:
if list1.val <= list2.val:
cur.next = list1
list1 = list1.next
else:
cur.next = list2
list2 = list2.next
cur = cur.next
# 合并后 list1 和 list2 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
cur.next = list1 if list1 else list2
return head.next

​88. 合并两个有序数组​

class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
res = []
p1 = p2 = 0
while p1 < m or p2 < n:
if p1 == m:
res.append(nums2[p2])
p2 += 1
elif p2 == n:
res.append(nums1[p1])
p1 += 1
elif nums1[p1] <= nums2[p2]:
res.append(nums1[p1])
p1 += 1
else:
res.append(nums2[p2])
p2 += 1
nums1[:] = res

​148. 排序链表​

​剑指 Offer II 077. 链表排序​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
# 获取中间节点并截断
def mid(self, head: ListNode) -> ListNode:
slow = head; fast = head.next
while fast and fast.next:
slow, fast = slow.next, fast.next.next
mid, slow.next = slow.next, None
return mid

def merge(self, l: Optional[ListNode], r: Optional[ListNode]) -> Optional[ListNode]:
cur = head = ListNode()
while l and r:
if l.val <= r.val:
cur.next = l
l = l.next
else:
cur.next = r
r = r.next
cur = cur.next
# 合并后 l 和 r 最多只有一个还未被合并完,我们直接将链表末尾指向未合并完的链表即可
cur.next = l if l else r
return head.next

def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next: return head
left = head; right = self.mid(head)
l = self.sortList(left)
r = self.sortList(right)
return self.merge(l, r)

​剑指 Offer II 026. 重排链表​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mid(self, head: ListNode) -> ListNode:
slow = head; fast = head.next
while fast and fast.next:
slow, fast = slow.next, fast.next.next
#截断
mid, slow.next = slow.next, None
return mid

def reverseList(self, head: ListNode) -> ListNode:
pre, cur = None, head
while cur:
# 存储当前链表的下一个节点为临时变量
tmp = cur.next
# 当前链表的下一个指向前一个链表
cur.next = pre
# pre, cur整体往后移动一个位置
pre, cur = cur, tmp
return pre

def merge(self, l1: ListNode, l2: ListNode):
h = cur = ListNode()
while l1 and l2:
cur.next = l1
l1 = l1.next
cur = cur.next
cur.next = l2
l2 = l2.next
cur = cur.next
cur.next = l1 if l1 else l2
return h.next

def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
if not head: return
l = head
r = self.mid(head)
r = self.reverseList(r)
self.merge(l, r)

​23. 合并K个升序链表​

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
if not lists:return
n = len(lists)
return self.merge(lists, 0, n-1)
def merge(self, lists, left, right):
if left == right:
return lists[left]
mid = left + (right - left) // 2
l1 = self.merge(lists, left, mid)
l2 = self.merge(lists, mid+1, right)
return self.mergeTwoLists(l1, l2)
def mergeTwoLists(self, l1, l2):
if not l1: return l2
if not l2: return l1
if l1.val < l2.val:
l1.next = self.mergeTwoLists(l1.next, l2)
return l1
else:
l2.next = self.mergeTwoLists(l1, l2.next)
return l2

​剑指 Offer 51. 数组中的逆序对​

class Solution:
def reversePairs(self, nums: List[int]) -> int:
def mergesort(nums, left, right):
if left >= right:
return 0
# 防止大数溢出
mid = left + (right - left) // 2
# 分治思想
cnt_l = mergesort(nums, left, mid)
cnt_r = mergesort(nums, mid + 1, right)
cnt_c = merge(nums, left, mid, right)

return cnt_l + cnt_r + cnt_c

def merge(nums, left, mid, right):
tmp, cnt = [], 0
i, j = left, mid + 1

while i <= mid and j <= right:
if nums[i] <= nums[j]:
tmp.append(nums[i])
i += 1
else:
tmp.append(nums[j])
j += 1
# 第二个序列插入时更新逆序数
cnt += (mid - i + 1)

if i <= mid:
tmp.extend(nums[i:mid+1])
else:
tmp.extend(nums[j:right+1])

nums[left:right+1] = tmp[:]
return cnt

return mergesort(nums, 0, len(nums)-1)

3. 堆排序

def heapify(a: list, n, i): 
largest = i
l = 2 * i + 1 # left = 2*i + 1
r = 2 * i + 2 # right = 2*i + 2

if l < n and a[i] < a[l]:
largest = l
if r < n and a[largest] < a[r]:
largest = r
if largest != i:
a[i],a[largest] = a[largest],a[i] # 交换
heapify(a, n, largest)

def heapSort(a: list):
n = len(a)
# Build a maxheap.
for i in range(n, -1, -1):
heapify(a, n, i)
# 一个个交换元素
for k in range(n-1, 0, -1):
a[k], a[0] = a[0], a[k] # 交换
heapify(a, k, 0)

堆排序(使用heapq)

import heapq

def heapSort (a: list):
heapq.heapify(a)
res = [heapq.heappop(a) for _ in range(len(a))]
return res

eg. ​​剑指 Offer II 059. 数据流的第 K 大数值​

class KthLargest:

def __init__(self, k: int, nums: List[int]):
self.k = k
self.q = nums
heapq.heapify(self.q)

def add(self, val: int) -> int:
heapq.heappush(self.q, val)
while len(self.q) > self.k:
heapq.heappop(self.q)
return self.q[0]


# Your KthLargest object will be instantiated and called as such:
# obj = KthLargest(k, nums)
# param_1 = obj.add(val)

4. 其他

​剑指 Offer II 075. 数组相对排序​

class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
n = max(arr1)
freq = [0] * (n+1)
for i in arr1:
freq[i] += 1
res = list()
for x in arr2:
res.extend([x] * freq[x])
freq[x] = 0
for x in range(n+1):
if freq[x] > 0: res.extend([x] * freq[x])
return res

标签:return,nums,int,self,next,算法,排序,def
From: https://blog.51cto.com/u_15905340/5919332

相关文章

  • 一致性哈希算法详解
    一致性哈希是什么,使用场景,解决了什么问题?转载:https://mp.weixin.qq.com/s/hJHMlbQpANwMjx9BetwkUg 1.如何分配请求大多数网站背后肯定不是只有一台服务器提供服务,因......
  • 数据挖掘算法-KNN算法
    ✅作者简介:热爱科研的算法开发者,Python、Matlab项目可交流、沟通、学习。......
  • 机器学习--Kmeans聚类算法
    1.1概述K-means算法是集简单和经典于一身的基于距离的聚类算法采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为类簇是由距离靠近的对象......
  • 机器学习--CF协同过滤推荐算法原理
    1.1概述什么是协同过滤(CollaborativeFiltering,简称CF)?首先想一个简单的问题,如果你现在想看个电影,但你不知道具体看哪部,你会怎么做?大部分的人会问问周围的朋友,看看最......
  • 算法基础课
    给定nn个正整数aiai,请你输出这些数的乘积的约数之和,答案对109+7109+7取模。输入格式第一行包含整数nn。接下来nn行,每行包含一个整数aiai。输出格式输出一个......
  • Vue中的diff算法深度解析
    模板tamplate经过parse,optimize,generate等一些列操作之后,把AST转为renderfunctioncode进而生成虚拟VNode,模板编译阶段基本已经完成了,那么这一章,我们来探讨一下Vue中的一......
  • 遗传算法——求解优化问题,参数分析(以求二维sphere最小值为例)
    遗传算法求解优化问题目录1.遗传算法的解读1.1参数编码1.1.1二进制编码1.1.2十进制编码1.2初始化群体的设定1.3适应度函数的设定1.4遗传操作设计1.4.1选择......
  • m基于PSO粒子群优化的Hammerstein模型参数辨识算法matlab仿真,对比LS最小二乘法
    1.算法概述        粒子群优化算法(PSO)是一种进化计算技术(evolutionarycomputation),1995年由Eberhart博士和kennedy博士提出,源于对鸟群捕食的行为研究。该......
  • Java—bouncycastle支持国密SM2的公钥加密算法
    Java—bouncycastle支持国密SM2的公钥加密算法java代码是依赖BouncyCastle类库,经修改此类库中的 SM2Engin 类的原码而来,用于支持SM2公钥加密算法,符合:《GM/T000......
  • javaScript_01_按照key排序
     javaScript_01_按照key排序前言Object.keys()与Objetc.values()实现按key排序前言最近做一个小程序项目需要用到腾讯地图的api,在计算sig的时候需要将参数按照......