• 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;
    }
    

    参考博客

  • 相关阅读:
    assert出问题了?
    UIWebView 禁止检测链接弹出UIActionSheet
    UIWebView 禁止检测链接弹出UIActionSheet
    Linux命令行下常用svn命令
    Linux命令行下常用svn命令
    续上文,Unity3D面试ABC
    续上文,Unity3D面试ABC
    部署 H3C CAS E0306
    部署 H3C CAS E0306
    H3C CAS 介绍 & 基本概念
  • 原文地址:https://www.cnblogs.com/zhcpku/p/14380149.html
Copyright © 2020-2023  润新知