Kth Largest Element in an Array解题心得

来源:互联网 发布:网络妖人再造天txt 编辑:程序博客网 时间:2024/05/18 13:31

Kth Largest Element in an Array解题心得

https://leetcode.com/problems/kth-largest-element-in-an-array/description/

题目描述

如题意所示:寻找第K大的数,这里选这道题的原因是因为,在查阅这道题更优的算法时,引出了一个重要而且可以在其他题目里使用的算法,即为Partition算法,以及一个极其精简版本的partition代码

Partition算法

在解这道题前先描述一种Partition算法:
无序序列S={a0,a1,a2,a3,....an}
随机取一个数为中间数pivot=ai
算法的目的是使得序列S分成两个个子序列S1,S2,
其中:
S1ai<=pivot
S2ai>pivot
实现方法通过两个头尾指针 left right,同时向中间过滤,直到碰到冲突的情况即对于左边S[left]>pivot,对于右边S[right]<=pivot,每次将两个冲突的元素交换;再重复两指针向中间过滤,直到两指针相遇即left>=right

  • 简单版本代码如下:

    int partition(vector<int> &nums, int begin, int end){     //[begin, end)        end--;        int pivot=nums[begin]        while(begin<end){            while(begin<=end&&nums[begin]<=pivot) begin++;            while(begin<=end&&nums[end]>pivot) end--;            if (begin<end) {                int temp=nums[begin];                nums[begin]=nums[end];                nums[end]=temp;            }        }        return begin;   }
  • 在查阅资料的过程中我发现一个更加精妙的一个实现:

    int partition(vector<int> &nums, int begin, int end){    //[begin, 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;}
  • 在这里的代码我们可以看到,这里没有用到交换的过程,而是通过pivot元素实现了全局的左右交换,而且代码的实现精简而又富有对称性

  • 对partition的研究和可以应用到快速排序算法中,甚至还能进一步实现three path partition问题(即将S分为三组,分别为小于,等于,大于)

将partition算法应用于求第k大的数

  • 以分治的思想我们可以逐步将问题分解化

    • 先对序列进行partition算法,分为两部分
    • 大于等于部分的元素个数与k比较
    • 决定第k大的数在哪一部分,再对新的部分重复上述partition算法,缩小求解的范围,最后得到第k大的数
    • 实现
    #include <stdio.h>class Solution {public:    int findKthLargest(vector<int>& nums, int k) {        int begin=0, end=nums.size();        while(begin<end){            int pivot=partition(nums, begin, end);            if (k-1==pivot){                return nums[pivot];            }            else if (k-1<pivot){                end=pivot;            }            else {                begin=pivot+1;            }        }        return nums[begin];    }    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;    }};
  • 算法的时间复杂度可以通过递推式得到:T(n)=T(n/2)+O(n)

  • 则实际复杂度为O(n)
原创粉丝点击