leecode 912 排序数组 力扣
十大经典排序算法 Python 版实现(附动图演示) - 知乎 图源 十大经典排序算法详细总结(含JAVA代码实现)_Java学习之道-优快云博客
快排
https://blog.youkuaiyun.com/liangkaiping0525/article/details/82558188
=============================================================================
# 从无序队列中挑取一个元素
# 把无序队列分割成独立的两部分
# 其中一部分的所有数据都比另外一部分的所有数据都要小
# 然后再按此方法对这两部分数据分别进行快速排序 整个排序过程可以递归进行 达到整个数据有序
# 简单来说:1挑元素、2分割分组、3递归---分组重复前两步
def quick_sort(nums, start, end):
if start >= end: # 递归的退出条件
return
i = start # i 为序列左边在开始位置的由左向右移动的游标 --- low
j = end # j 为序列右边末尾位置的由右向左移动的游标 --- high
mid = nums[i] # 设定起始的【基准元素】
while i < j:
while i < j and nums[j] >= mid: # high向左移动: 如果low与high未重合,high(右边)指向的元素>=基准元素
j -= 1
nums[i] = nums[j] # 走到此位置时high指向一个比基准元素小的元素,将high指向的元素放到low的位置上,此时high指向的位置空着
# # 接下来移动low找到符合条件的元素放在此处
while i < j and nums[i] < mid: # low向右移动: 如果low与high未重合,low指向的元素<基准元素
i += 1
nums[j] = nums[i] # 此时low指向一个比基准元素大的元素,将low指向的元素放到high空着的位置上,此时low指向的位置空着
# # 之后进行下一次循环,将high找到符合条件的元素填到此处
# 退出循环后,low与high重合. 此时: 左边的元素都比基准元素小,右边的元素都比基准元素大
nums[i] = mid # 两边ok,还原将基准元素放到该位置
quick_sort(nums, start, i - 1) # 对基准元素左边的子序列进行快速排序 # start :0 low -1 原基准元素靠左边一位
quick_sort(nums, i + 1, end) # 对基准元素右边的子序列进行快速排序 # low+1 : 原基准元素靠右一位 end: 最后
# 注意这里已经不是 quick_sort(nums, start, mid-1)
# 注意这里已经不是 quick_sort(nums, mid+1, end)
if __name__ == '__main__':
nums = [54, 26, 93, 17, 77, 31, 44, 55, 20]
quick_sort(nums, 0, len(nums)-1)
print(nums)
归并
https://leetcode-cn.com/problems/sort-an-array/solution/pai-xu-shu-zu-by-leetcode-solution/
# 把长度为n的输入序列分成长度 n/2的子序列
# 对两个子序列采用归并排序
# 合并所有子序列
# 采用是【分治法】 先分成子序列 让子序列有序 再将子序列间有序 合并
def merge_sort(nums, start, end):
if start == end:
return
mid = (start + end)//2
merge_sort(nums, start, mid)
merge_sort(nums, mid+1, end)
i, j = start, mid +1
tmp = []
while(i<= mid or j<= end):
if (i> mid) or (j<= end and nums[j]< nums[i]):
tmp.append(nums[j])
j+=1
else:
tmp.append(nums[i])
i+=1
nums[start: end+1]= tmp
if __name__ == '__main__':
nums = [54, 26, 93, 17, 77, 31, 44, 55, 20]
merge_sort(nums,0, len(nums)-1)
print(nums)
堆排
https://leetcode-cn.com/problems/sort-an-array/solution/pai-xu-shu-zu-by-leetcode-solution/
# 代码
# 解释 https://blog.youkuaiyun.com/june_young_fan/article/details/82014081
# =============================================================================
# 给定某个节点的下标root
# 可计算出其他下标 ---父节点(root-1)//2 ---左子节点 2*root + 1 ---右子节点 2*root + 2
# 调整堆 max_heapify()
# 建立堆 build_heap()
# 堆排序的思想:
# 先将待排序的序列建成大根堆 使得每个父节点的元素大于等于它的子节点
# 此时整个序列最大值即为堆顶元素 我们将其与末尾元素交换 使末尾元素为最大值 然后再调整堆顶元素使得剩下的 n-1 个元素仍为大根堆
### 调整列表中的元素 并保证以root为根的堆 是一个大根堆
def max_heapify(heap, root, heap_len):
long = heap_len
while (2*root+ 1 < long): # 循环条件:从(heap_len -2)//2处开始调整 一直调整到第一个根节点
left = 2*root + 1 # 大根堆数据结构就是一完全二叉树 存在这个关系 不信画图 但是是以一维数组存在
right = 2*root + 2 # 先确定左右哪个子节点更大 用来调整交换root
if (long <= right or heap[right] < heap[left]):
tmp = left
else:
tmp = right
if (heap[root] < heap[tmp]): # 再将root与左右较大子节点进行比较 确认互换与否
heap[root], heap[tmp] = heap[tmp], heap[root]
root = tmp
else:
break
def heap_sort(nums):
N = len(nums)
for i in range(N-1, -1, -1): ### 【构造一个大顶堆】 将堆中所有数据重新排序 自底向上建堆 调整后列表的第一个元素最大
max_heapify(nums, i, N)
print(nums)
print('---')
for i in range(N-1, -1, -1): ### 【重复调整堆】 将根节点取出与最后一位做对调 此时最后一位即最大 然后将剩余的前面len-1个节点 再递归的调整为最大堆
nums[i], nums[0] = nums[0], nums[i]
max_heapify(nums, 0, i)
print(nums)
print('---')
if __name__ == '__main__':
nums = [54, 26, 93, 17, 77, 31, 44, 55, 20]
heap_sort(nums)
print(nums)
二分
求平方根,二分查找,以及牛顿下降: http://leetcode.cn/problems
二分的使用条件:1-区间确定,为[a, b)左臂右开;2-输入已知单调。复杂度从N降低到log(N)
前面快排是针对无序,Nlog(N);
class Solution(object):
def mySqrt(self, x):
left, right = 0, x + 1 # [left, right)
while left < right:
mid = left + (right - left) // 2
if mid ** 2 == x:
return mid
if mid ** 2 < x:
left = mid + 1
else:
right = mid
return left - 1
# 调用示例
sl = Solution()
result = sl.mySqrt(10)
print("结果为:", result)