本文主要讨论quicksort和寻找第k大元素的两个相关问题。
力扣连接https://leetcode-cn.com/problems/sort-an-array/【排序算法精华3】快速排序 (上)_哔哩哔哩_bilibili"五点七边-算法学习" QQ交流群:539835344快速排序(英语:Quicksort),简称快排,是一种排序算法,最早由东尼·霍尔提出。正如它的名字所暗示的那样,快速排序的最大优点在于它的速度非常快。在实现的比较好的时候,快速排序往往比归并排序、堆排序等优秀的排序算法更快...感谢:本视频动画使用manim数学引擎制作: http://github.com/3b1b/man
https://www.bilibili.com/video/BV1rV411j7f6?from=search&seid=11355076395128076944&spm_id_from=333.337.0.0
快速排序法的思路是基于分而治之,:将数组不断地一分为二,再去处理更小的部分。但是,当实际写代码时,递归时具体分块的实现函数的实现总是让我难受,在这个函数里会使用到两个指针,一个i,一个j,它们是用来干嘛的呢?
为了回答这个问题,首先要知道partition这个函数用来干嘛,他有两个任务:1.将数组中小于和大于pivot的元素分别放到它的两边;2. 返回pivot的index。针对这个过程,很容易想象,我们需要
1. 实现遍历,其中一个指针的作用就是实现从左到右的完全遍历(没必要遍历pivot)
2. 指向pivot元素应该出现的位置,这是我们需要返回的index
基于这些提示,来尝试实现一下这个函数,这里我们自动选择最右侧元素为每次的pivot元素
void swap(vector<int> &array, int idx1, int idx2) {
int tmp = array[idx1];
array[idx1] = array[idx2];
array[idx2] = tmp;
return;
}
int partition(vector<int> &array, int l_idx, int r_idx) {
int i = l_idx, j = l_idx, pivot = r_idx;
while (j < r_idx) {
if (array[j] < array[pivot]) {
swap(array, i, j);
i++;
}
j++;
}
swap(array, r_idx, i);
return i;
}
在实现了partition这个函数后,基于它,接下来快速排序的实现就很容易了,一个简单的递归就可以搞定,
void quickSort(vector<int>& array,int left,int right)
{
if (right<=left) {return;}
int q = partition(array, left,right);
//注意这里index的选择,没有+1或者-1,会让程序陷入死循环。
quickSort(array,left,q-1);
quickSort(array,q+1,right);
}
除了实现快速排序,当我们想要寻找第k大的元素时,我们也可以基于partition来实现,同样是递归的思想,唯二不同的是终止条件和少了一半的递归操作。
int getNthLargestNum(vector<int>&array,int k,int left,int right)
{
int q= partition(array,left,right);
if(q==array.size()-k) return array[q];
else if(q<array.size()-k)
{
return getNthLargestNum(array,k,q+1,right);
}
else
{
return getNthLargestNum(array,k,left,q-1);
}
}