【算法学习】排序问题

文章探讨了在数组中寻找局部最小值的策略,以及如何使用二分法避免溢出问题。还详细阐述了归并排序的合并过程和小和问题的解决方法,指出这些问题与逆序对和荷兰国旗问题的关联。此外,文章深入介绍了堆结构,包括大根堆的构建和维护,以及堆排序的应用场景。最后,提到了快速排序、堆排序和归并排序在不同条件下的选择策略。
摘要由CSDN通过智能技术生成

1. 局部最小和二分法

一个数组从0到N位置一定存在局部最小值,即x(m-1)>x(m)<x(m+1), 不停寻找局部最小位置作为二分点。

2. 求中点

(1)mid =(L+R)/2
常见写法,但(L+R)容易发生溢出
(2)mid = L+(R-L)/2
(3)mid = L+(R-L)>>1
右移操作比除2更快

3. 归并排序的合并

在这里插入图片描述
p1<M和p2<R是判断越界

4. 小和问题

在这里插入图片描述

等同于对于每个数,给右边的数的贡献。例如,1的右边有四个数比它大,则1的贡献是4个1;3的右边有两个,贡献是2个3……
此时求解小和等同于归并排序的merge操作。
例如,我们可以先求1和3的数组的小和,即把1和3看成两个有序数组merge,得到1个1;
接着把数组13和4merge,得到1个1和1个3,依次类推
在这里插入图片描述
代码:
在这里插入图片描述

在这里插入图片描述

5. 逆序对问题

在这里插入图片描述
与小和问题一样

6. 荷兰国旗问题

在这里插入图片描述
对于问题一:
例如arr=[3 5 6 7 4], num=5
设置一个x,代表小于等于区,初始x=0,
从i=0遍历到最后:
(1)arr[i]<=num, arr[i]和arr[x+1]交换,然后x++,i++
(2)arr[i]>num,i++
对于问题二:
在这里插入图片描述
由荷兰国旗问题可以推出快排。

7. 堆结构

  • 堆事实上就是一种完全二叉树

  • 堆排序的空间复杂度是最小的

  • 优先级队列就是堆(java中PriorityQueue就是默认小根堆,也可以通过修改比较器变成大根堆)

  • 堆和数组的对应关系:
    在这里插入图片描述
    对应下标:
    在这里插入图片描述
    规则是对于i位置的节点:
    左孩子:2i+1
    右孩子:2
    i+2
    父节点:(i-1)/2

  • 大根堆:
    最大值在根节点,每个父节点都比它孩子节点大
    (1)上移操作(heapInsert):在叶子节点插入一个数(即在数组最尾端放一个数字),通过不断上移形成新的大根堆
    在这里插入图片描述
    (2)下移操作(heapify):某个父节点变成一个更小的数,不断将数字和其最大的孩子比较交换,重新构建大根堆;
    在这里插入图片描述
    代码中heapsize是防止越界,如果左孩子小于heapsize代表节点下方还有孩子节点,有时候我们不考虑整个数组,只考虑前几个数字
    (4)堆排序
    先构建一个大根堆,每次删除数组中的最大值(交换根节点和最后一个节点),然后断掉新的最后节点,然后剩下部分重新构建大根堆
    在这里插入图片描述
    构建大根堆的方法有两种:
    (1)一个一个插入,从上到下构建大根堆
    (2)首先构造一个二叉树(无序),然后自下而上构造大根堆,比方法(1)更好
    在这里插入图片描述
    堆排序应用:
    假设一个数组排序,每个数字正确排放的位置都不会移动超过k步,怎么排序?
    从i=0位置开始,每次取i到(i+k)位置数字,将其构建成小根堆,i位置此时一定是正确值,依次往后操作

8. 桶排序

pass

9. 排序问题总结

在这里插入图片描述

  • 快排是最优选,如果有空间限制再选堆,需要稳定性选归并。

  • 坑:很难,经典快排的划分不具有稳定性,需要进行论文级别的研究
    在这里插入图片描述

  • 有时候需要结合NlogN和N^2的算法:
    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值