标签:
https://leetcode.com/problems/kth-largest-element-in-an-array/
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.
最容易想到的方法是使用排序来做,按从大到小进行排序,然后返回k-1位置处的元素,但是o(nLogn)的时间复杂度显然不是我们想要的。
首先对数组元素进行heapify,建立一个大顶堆,既然是要找第k大的元素,那么可以对该大顶堆进行k-1次extractMax()操作,此时堆顶即为第K大的元素。建堆的时间复杂度为o(n),同时每一次extractMax()操作都需要进行时间复杂度为o(logn)的heapify()操作来维持堆序性,因此总的时间复杂度为o(n + klogn),显然优于排序。代码如下:
/** * Author : Jianxin Zhou */ class Solution { public: int findKthLargest(vector<int>& nums, int k) { heapSize_ = nums.size(); createMaxHeap(nums); for (int i = 0; i < k - 1; ++i) { exactMax(nums); } return nums[0]; } private: int heapSize_; inline int leftChild(int parent) { return (parent << 1) + 1; } inline int rightChild(int parent) { return (parent << 1) + 2; } inline int parent(int child) { return (child - 1) >> 1; } void createMaxHeap(vector<int> &nums) { int indexForHeapify = parent(heapSize_ - 1); for (int i = indexForHeapify; i >= 0; --i) { maxHeapify(nums, i); } } // 从位置i处进行下滤,保持大顶堆的偏序性 void maxHeapify(vector<int> &nums, int i) { int left = leftChild(i); int right = rightChild(i); int largest = i; if (left < heapSize_ && nums[left] > nums[largest]) { largest = left; } if (right < heapSize_ && nums[right] > nums[largest]) { largest = right; } if (largest != i) { swap(nums[largest], nums[i]); maxHeapify(nums, largest); } } void exactMax(vector<int> &nums) { swap(nums[0], nums[heapSize_ - 1]); --heapSize_; maxHeapify(nums, 0); } };
快速排序的核心思想在于,挑选一个pivot元素,并将其放在经排序后应该所处的正确的位置,然后再递归的对该pivot两边的元素进行partition操作,挑选pivot元素置于正确的位置。(简单分析下最坏情况下的时间复杂度,每次挑选的pivot位置最终所处的正确的位置都在数组的两端,那么每次对该pivot元素进行归位时,需要o(n)的时间复杂度,那么最坏情况是o(n2))。
那么对于解决本问题而言,我们不必进行完整的快排操作,只要当前pivot元素最终落在第k大的元素的位置时,我们即停止快排。
[LeetCode] Kth Largest Element in an Array
标签:
原文地址:http://www.cnblogs.com/jianxinzhou/p/4676122.html