Cover image for 面试经典150题 P215 数组中的第K个最大元素

面试经典150题 P215 数组中的第K个最大元素


时间轴

时间轴

2025-12-05

init

快排,堆

题目:

堆排序

完全二叉树结点进行编号,有如下关系

项目1-based 编号(根=1)0-based 编号(根=0)
左孩子left(i)=2i\text{left}(i)=2i left(i)=2i+1 \text{left}(i)=2i+1
右孩子right(i)=2i+1 \text{right}(i)=2i+1 right(i)=2i+2 \text{right}(i)=2i+2
父节点parent(i)=i/2i>1 \text{parent}(i)=\lfloor i/2 \rfloor(i>1)parent(i)=(i1)/2i>0 \text{parent}(i)=\lfloor (i-1)/2 \rfloor(i>0)
至少有左孩子的条件2in 2i \le n 2i+1<n 2i+1 < n
右孩子存在条件2i+1n 2i+1 \le n 2i+2<n 2i+2 < n
叶节点条件i>n/2i > \lfloor n/2 \rfloori>(n2)/2 i > \lfloor (n-2)/2 \rfloor 2i+1n2i+1 \ge n
只有左孩子条件2i=n2i = n 2i+1<n 2i+1 < n 2i+2n 2i+2 \ge n
深度(root 层=1)log2i+1 \lfloor \log_2 i \rfloor +1 log2(i+1)+1 \lfloor \log_2 (i+1) \rfloor +1
深度(root 层=0)log2i \lfloor \log_2 i \rfloor log2(i+1) \lfloor \log_2 (i+1) \rfloor

堆排序:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
#include <vector>using std::vector;class Solution {    private:        void heapify(vector<int> &vec, int curr, int n)        {                int left = curr * 2 + 1;                int right = curr * 2 + 2;                int largest = curr;                if (left < n && vec[left] > vec[largest]) {                        largest = left;                }                if (right < n && vec[right] > vec[largest]) {                        largest = right;                }                if (largest != curr) {                        std::swap(vec[largest], vec[curr]);                        //由于交换了父节点和子节点,因此可能对子节点的子树造成影响,所以对子节点的子树进行调整。                        heapify(vec, largest, n);                }        }        void buildMaxHeap(vector<int> &vec)        {                int n = vec.size();                // 最后一个节点的位置为n-1,所以父节点的位置为(n-1-1)/2。                for (int i = (n - 2) / 2; i >= 0; i--) {                        heapify(vec, i, n);                }        }    public:        int findKthLargest(vector<int> &nums, int k)        {                int n = nums.size();                buildMaxHeap(nums);                for (int i = 0; i < k - 1; i++) {                        // pop                        std::swap(nums[0], nums[n - 1]);                        n--;                        heapify(nums, 0, n);                }                return nums[0];        }};

快速排序

注意 hoare 写法不关心与 pivot 相等的在哪,只要求左边<= pivot, 右边>= pivot

123456789101112131415161718192021222324252627282930313233343536373839
#include <vector>using std::vector;class Solution {    private:        int quick_sort(vector<int> &nums, int start, int end, int k)        {                if (end <= start) {                        return nums[k];                }                int pivot = nums[(start + end) / 2];                int left = start - 1;                int right = end + 1;                while (left < right) {                        do {                                left++;                        } while (nums[left] < pivot);                        do {                                right--;                        } while (nums[right] > pivot);                        if (left < right) {                                std::swap(nums[left], nums[right]);                        }                }                // start..=right, right+1..=end                if (k<= right) {                        return quick_sort(nums, start, right, k);                } else {                        return quick_sort(nums, right+1, end, k);                }        }    public:        int findKthLargest(vector<int> &nums, int k)        {                int n = nums.size();                // 第K个最大,即第n-k最小                return quick_sort(nums, 0, n - 1, n - k);        }};
评论加载中…