//小根堆 voidheap_build(vector<int> &nums, int rootPos, int lastPos){ int leftPos = rootPos * 2 + 1; if (leftPos < lastPos) { int rightPos = leftPos + 1; int maxPos = leftPos; if (rightPos < lastPos) { maxPos = nums[leftPos] < nums[rightPos] ? leftPos : rightPos; } if (nums[maxPos] < nums[rootPos]) { swap(nums[maxPos], nums[rootPos]); heap_build(nums, maxPos, lastPos); } } }
voidheap_sort(vector<int> &nums){ int n = nums.size(); for (int i = n / 2; i >= 0; i--) { heap_build(nums, i, n); } for (int i = n - 1; i >= 0; i--) { swap(nums[0], nums[i]); heap_build(nums, 0, i); } }
而如果是像topk这种, 是慢慢插入的, 使用上滤插入建堆更好
//小根堆 voidheap_build(vector<int> &nums, int rootPos, int lastPos){ int leftPos = rootPos * 2 + 1; if (leftPos < lastPos) { int rightPos = leftPos + 1; int maxPos = leftPos; if (rightPos < lastPos) { maxPos = nums[leftPos] < nums[rightPos] ? leftPos : rightPos; } if (nums[maxPos] < nums[rootPos]) { swap(nums[maxPos], nums[rootPos]); heap_build(nums, maxPos, lastPos); } } }
voidheap_sort(vector<int> &nums){ int n = nums.size(); for (int i = n / 2; i >= 0; i--) { heap_build(nums, i, n); } for (int i = n - 1; i >= 0; i--) { swap(nums[0], nums[i]); heap_build(nums, 0, i); } }
//上滤 voidshift_up(vector<int> &nums){ int curr = nums.size() - 1; int val = nums.back(); while (curr > 0 && val < nums[curr / 2]) { nums[curr] = nums[curr / 2]; curr /= 2; } nums[curr] = val; }
intfindKthLargest(vector<int> &nums, int k){ int n = nums.size(); vector<int> small_heap; for (int i = 0; i < n; i++) { if (small_heap.size() < k) { // small_heap.insert(small_heap.begin(), nums[i]); // heap_build(small_heap, 0, small_heap.size()); small_heap.push_back(nums[i]); shift_up(small_heap); } elseif (nums[i] > small_heap.front()) { small_heap[0] = nums[i]; heap_build(small_heap, 0, small_heap.size()); } } return small_heap[0]; }
boolcheck(vector<vector<int>> &matrix, int mid, int k, int n){ int i = n - 1; int j = 0; int num = 0; //每次对于「猜测」的答案 mid,计算矩阵中有多少数不大于 mid //如果数量不少于 k,那么说明最终答案 x 不大于 mid; //如果数量少于 k,那么说明最终答案 x 大于 mid。 while (i >= 0 && j < n) { if (matrix[i][j] <= mid) { num += i + 1; j++; } else { i--; } } return num >= k; }
intkthSmallest2(vector<vector<int>> &matrix, int k){ int n = matrix.size(); int left = matrix[0][0]; int right = matrix[n - 1][n - 1]; while (left < right) { int mid = left + ((right - left) >> 1); if (check(matrix, mid, k, n)) { //<=mid的个数>=k 找左边界 right = mid; //向左上角收缩 } else { left = mid + 1; //向右下角扩大 } } return left; }
classSolution { public: vector<int> maxSlidingWindow(vector<int>& nums, int k){ int n = nums.size(); priority_queue<pair<int, int>> q; for (int i = 0; i < k; ++i) { q.emplace(nums[i], i); } vector<int> ans = {q.top().first}; for (int i = k; i < n; ++i) { q.emplace(nums[i], i); while (q.top().second <= i - k) { q.pop(); } ans.push_back(q.top().first); } return ans; } };
单调双端队列
classSolution { public: vector<int> maxSlidingWindow(vector<int>& nums, int k){ int n = nums.size(); deque<int> q; for (int i = 0; i < k; ++i) { while (!q.empty() && nums[i] >= nums[q.back()]) { q.pop_back(); } q.push_back(i); }
vector<int> ans = {nums[q.front()]}; for (int i = k; i < n; ++i) { while (!q.empty() && nums[i] >= nums[q.back()]) { q.pop_back(); } q.push_back(i); while (q.front() <= i - k) { q.pop_front(); } ans.push_back(nums[q.front()]); } return ans; } };