快排-归并-堆排,二分

leecode 912 排序数组 力扣

十大经典排序算法 Python 版实现(附动图演示) - 知乎 图源 十大经典排序算法详细总结(含JAVA代码实现)_Java学习之道-CSDN博客

快排

https://blog.csdn.net/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.csdn.net/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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值