LeetCode OJ 之 Kth Largest Element in an Array(数组中的第k大元素)

来源:互联网 发布:mac虚拟机哪个好 编辑:程序博客网 时间:2024/06/04 18:21

题目:

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

For example,
Given [3,2,1,5,6,4] and k = 2, return 5.

Note: 
You may assume k is always valid, 1 ≤ k ≤ array's length.

思路:

1、基于快排partition的思路

2、采用堆排序。类似剑指Offer的一题:最小的k个数。

代码1:

基于快排partition的思路

class Solution {public:    int findKthLargest(vector<int>& nums, int k)     {        int len = nums.size();        if(len == 0)            return -1;        int index = 0;        int begin = 0 , end = len - 1;        srand((unsigned)time(NULL));        int flag = rand() % 2;//两种partition方法随机选择一个        if(flag == 1)            index = partition1(nums , begin , end);        else            index = partition2(nums , begin , end);        //第k大数的下标是(len-k)          while(index != len - k)        {            if(index > len - k)                end = index - 1;            else                begin = index + 1;            if(flag == 1)                index = partition1(nums , begin , end);            else                index = partition2(nums , begin , end);        }        return nums[index];    }    //两种partition方法    int partition1(vector<int> &nums , int left , int right)    {        if(left == right)            return left;        int i = left , j = right;        int pivot = nums[left];        while(i < j)        {            while(i < j && nums[j] > pivot)                j--;            if(i < j)                nums[i++] = nums[j];            while(i < j && nums[i] < pivot)                i++;            if(i < j)                nums[j--] = nums[i];        }        nums[i] = pivot;        return i;    }    int partition2(vector<int> &nums , int left , int right)    {        if(left == right)            return left;        int index = left ;        int pivot = nums[left];        for(int i = left + 1 ; i <= right ; i++)        {            if(nums[i] < pivot)            {                index++;                swap(nums[index] , nums[i]);            }        }        swap(nums[left] , nums[index]);        return index;    }};


代码2:

堆排序(适合处理大数据):

class Solution {public:    int findKthLargest(vector<int>& nums, int k)     {                 int len = nums.size()-1;        BuildHeap(nums);//建堆        //下面对堆排序,每次取出堆顶nums[0](即最大值),然后对除去堆顶的元素的堆维护最大堆的性质        for( ; len >= 0 ; len--)        {            swap(nums[0] , nums[len]);//把堆尾和堆顶交换            MaxHeapify(nums , 0 , len);//维护堆的性质,此时已经把堆的最后一个元素删掉        }        return nums[nums.size() - k];    }    //建堆,即从len/2-1开始向前,对结点与其子节点进行比较,然后调整,使得以i为根结点的子堆符合最大堆(为什么从len/2-1开始:因为len/2向后都是叶结点都已经满足最大堆性质)    void BuildHeap(vector<int> &nums)    {        int len = nums.size();        for(int i = len/2 - 1 ; i >= 0 ; i--)            MaxHeapify(nums , i , len);    }    //对于开始下标为0的数组,两个子节点的下标为2i+1和2i+2    int left(int i)    {        return 2 * i + 1;    }    int right(int i)    {        return 2 * i + 2;    }    //维护堆的性质,即使以当前点i为根结点的堆满足最大堆,当前点与左右孩子比较,然后最大的放到i,然后对孩子结点递归,这里的len是堆的个数,不是下标    void MaxHeapify(vector<int> &nums , int i , int len)    {        int l = left(i) , r = right(i);//左右孩子下标        int largest = i;//保存i和左右孩子中值最大的下标        if(l < len && nums[l] > nums[i])            largest = l;        if(r < len && nums[r] > nums[largest])            largest = r;        //如果孩子结点较大,则调整,然后继续对孩子结点递归,维护孩子的最大堆性质        if(largest != i)        {            swap(nums[largest] , nums[i]);            MaxHeapify(nums , largest , len);        }    }};



0 0
原创粉丝点击