Partition算法及其应用

Partition算法及其应用

本文记录partition算法的两种实现方案,及其经典应用场景

Partition算法

partition算法的作用是选定一个元素pivot,然后将元素划分为两个部分,小于pivot的放在左边,大于pivot的放在右边。
实现上,可以分为单向扫描和双向扫描两种方案。

单向扫描算法:

单向扫描,是利用一个指针扫描数组,凡是小于pivot的都放到数组的左端,最后把把pivot放回中间位置。

int partition(vector<int> &nums, int begin, int end)
{
    int pivot = nums[begin];
    int pos = begin;
    for(int i = begin+1; i < end; ++i) {
        if(nums[i] <= pivot) {
            swap(nums[++pos],nums[i]);
        }
    }
    swap(nums[pos], nums[begin]);
    return pos;
}

双向扫描算法:

双向扫描因为交换次数更少,效率更高一些。使用两个指针分别从头部和尾部进行扫描,头部遇到的大于pivot的元素和尾部遇到的小于pivot的元素进行交换。

int partition(vector<int> &nums, int begin, int end)
{
    int pivot = nums[begin];
    while(begin < end) {
        while(begin < end && nums[--end] >= pivot);
        nums[begin] = nums[end];
        while(begin < end && nums[++begin] <= pivot);
        nums[end] = nums[begin];
    }
    nums[begin] = pivot;
    return begin;
}

不过我更习惯这种闭区间写法:

int partition(int a[], int l, int r)
{
    int x = a[l];
    int i = l;
    int j = r;
    while (i < j) {
        while (i < j && a[j] >= x) j--;
        if (i < j) a[i++] = a[j];
        while (i < j && a[i] < x) i++;
        if (i < j) a[j--] = a[i];
    }
    a[i] = x;
    return i;
}

注意事项

无论是开区间还是闭区间,都是 while(i < j) if (i < j),这一点与二分查找不同:开区间 while (l < r) 闭区间 while (l <= r)

应用

快速排序算法:

经典快速排序。

void quickSort(vector<int> &nums, int begin, int end)
{
    if(end - begin <= 1) return;
    int mid = partition(nums, begin, end);
    quickSort(nums, begin, mid);
    quickSort(nums, mid, end);
}

快速选择算法:

选择数组中的第k大元素 LeetCode 215. Kth Largest Element in an Array

int findKthLargest(vector<int> &nums, int k)
{
    int len = nums.size();
    int res = 0;
    int left = 0;
    int right = len;
    while(left < right) {
        int pos = partition(nums, left, right);
        if(pos == len-k) {
            res = nums[pos];
            break;
        } else if(pos < len-k) {
            left = pos+1;
        } else {
            right = pos;
        }
    }
    return res;
}

参考博客

posted @ 2021-02-05 23:01  与MPI做斗争  阅读(288)  评论(0编辑  收藏  举报