堆
#include <vector>
using namespace std;
class Solution {
public:
// 自上而下调整大顶堆,O(logn)
void adjustHeap(vector<int> &nums, int len, int curIndex) {
int leftChild = 2 * curIndex + 1;
int temp = nums[curIndex];
while (leftChild <= len - 1) {
// 如果有右孩子,且更大,就换成右孩子
if (leftChild < len - 1
&& nums[leftChild + 1] > nums[leftChild])
leftChild++;
if (nums[leftChild] <= temp) break;
nums[curIndex] = nums[leftChild];
curIndex = leftChild;
leftChild = 2 * curIndex + 1;
}
nums[curIndex] = temp;
}
// 自底向上建堆,O(n)
void bottomUp(vector<int> &nums) {
int n = nums.size();
// 从最后一个非叶子节点开始往上
for (int i = n / 2 - 1; i >= 0; i--)
adjustHeap(nums, n, i);
}
// 插到末尾,再自底向上调整
void heapInsert(vector<int> &nums, int len, int val) {
nums[len++] = val;
int curIndex = len - 1;
int parent = (curIndex - 1) / 2;
while (nums[curIndex] > nums[parent]) {
swap(nums[curIndex], nums[parent]);
curIndex = parent;
parent = (curIndex - 1) / 2;
}
}
// 自顶向下建堆,O(nlogn)
void topDown(vector<int> &nums) {
int n = nums.size();
for (int i = 0; i < n; ++i)
heapInsert(nums, i, nums[i]);
}
void heapSort(vector<int> &nums) {
int n = nums.size();
// 堆的大小
int len = nums.size();
// 只需要 n - 1 次
for (int i = 1; i < n; ++i) {
swap(nums[0], nums[--len]);
adjustHeap(nums, len, 0);
}
}
vector<int> sortArray(vector<int> &nums) {
bottomUp(nums);
// topDown(nums);
heapSort(nums);
return nums;
}
};
class Solution {
public:
// 每次从链表数组中找到最小的头节点,加入最终结果
ListNode *mergeKLists(vector<ListNode *> &lists) {
// 没有元素直接返回
if (lists.empty()) return nullptr;
ListNode *dummyHead = new ListNode(0, nullptr);
ListNode *pre = dummyHead;
int len = lists.size();
while (true) {
// 记录当前所有链表中头节点值最小的链表在 lists 中的下标
int minHeadIndex = -1;
// 遍历每一条链表的头部,找到最小的头节点
for (int i = 0, finished = 0; i < len; ++i) {
if ((lists[i] != nullptr) &&
(minHeadIndex == -1 || (lists[i]->val < lists[minHeadIndex]->val)))
minHeadIndex = i;
}
// 已经找不到元素了(每个链表都是空的),则返回
if (minHeadIndex == -1) return dummyHead->next;
// 否则,移出最小元素,并且合并到最终结果中
ListNode *node = lists[minHeadIndex];
lists[minHeadIndex] = lists[minHeadIndex]->next;
node->next = nullptr;
pre->next = node;
pre = pre->next;
// 判断是否只剩下一条链表
int finished = 0;
for (ListNode *curHead: lists)
if (curHead == nullptr) finished++;
if (finished >= len - 1) break;
}
// 把最后剩下的一条链表直接接上
for (ListNode *curHead: lists) {
if (curHead != nullptr) {
pre->next = curHead;
return dummyHead->next;
}
}
return dummyHead->next;
}
};
class Solution {
public:
// 合并两个链表
ListNode *mergeTwoLists(ListNode *a, ListNode *b) {
if ((!a) || (!b)) return a ? a : b;
ListNode *dummyHead = new ListNode(0, nullptr);
ListNode *pre = dummyHead;
ListNode *p = a, *q = b;
while (p && q) {
if (p->val < q->val) {
pre->next = p;
p = p->next;
} else {
pre->next = q;
q = q->next;
}
pre = pre->next;
}
pre->next = (p ? p : q);
return dummyHead->next;
}
// 遍历链表数组,每次把一整条链表和最终链表合并
ListNode *mergeKLists(vector<ListNode *> &lists) {
ListNode *res = nullptr;
for (int i = 0; i < lists.size(); ++i)
res = mergeTwoLists(res, lists[i]);
return res;
}
};
class Solution {
public:
// 合并两个链表
ListNode *mergeTwoLists(ListNode *a, ListNode *b) {
if ((!a) || (!b)) return a ? a : b;
ListNode *dummyHead = new ListNode(0, nullptr);
ListNode *pre = dummyHead;
ListNode *p = a, *q = b;
while (p && q) {
if (p->val < q->val) {
pre->next = p;
p = p->next;
} else {
pre->next = q;
q = q->next;
}
pre = pre->next;
}
pre->next = (p ? p : q);
return dummyHead->next;
}
ListNode *merge(vector<ListNode *> &lists, int left, int right) {
if (left > right) return nullptr;
if (left == right) return lists[left];
int mid = left + ((right - left) >> 1);
return mergeTwoLists(merge(lists, left, mid), merge(lists, mid + 1, right));
}
// 分治合并
ListNode *mergeKLists(vector<ListNode *> &lists) {
return merge(lists, 0, lists.size() - 1);
}
};
class Solution {
public:
struct cmp {
bool operator()(ListNode *a, ListNode *b) {
return (*a).val > (*b).val;
}
};
// 使用小顶堆,只有初始化堆的时候要遍历一次数组,之后每次把堆顶节点并入最终链表,并且把堆顶节点的后继加入堆中
ListNode *mergeKLists(vector<ListNode *> &lists) {
// 没有元素直接返回
if (lists.empty()) return nullptr;
ListNode *dummyHead = new ListNode(0, nullptr);
ListNode *pre = dummyHead;
// 小顶堆
priority_queue<ListNode *, vector<ListNode *>, cmp> heap;
// 初始化小顶堆,把所有的链表头节点加入其中
for (ListNode *curHead: lists) {
if (curHead == nullptr) continue;
heap.push(curHead);
curHead = curHead->next;
}
while (!heap.empty()) {
// 取出最小节点,并加入到最终的链表中
ListNode *node = heap.top();
heap.pop();
pre->next = node;
pre = pre->next;
// 如果后面的节点非空的话,就加入到堆中
if (node->next != nullptr)
heap.push(node->next);
}
return dummyHead->next;
}
};
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
vector<vector<int>> lines(n, vector<int>(2, 0));
for (int i = 0; i < n; ++i)
cin >> lines[i][0] >> lines[i][1];
// 根据线段的左端点排序
sort(lines.begin(), lines.end(),
[](vector<int> &v1, vector<int> &v2) { return v1[0] < v2[0]; });
// 小顶堆,根据线段的右端点排序
priority_queue<int, vector<int>, greater<int>> heap;
int res = 0;
// 任何一个重合的区域,一定有一个左端点最大的,下面的循环就是考虑这个最大的左端点是谁
// [ ]
// [ ]
// [ ]
// 最大的左端点
for (int i = 0; i < n; ++i) {
// 堆中保存着的线段的右端点比当前线段的左端点还小
// 说明没有重合的地方,也不会与后续的线段重合,全部弹出
while (!heap.empty() && heap.top() <= lines[i][0])
heap.pop();
heap.emplace(lines[i][1]);
res = max(res, (int) heap.size());
}
cout << res;
}
#include <vector>
#include <queue>
#include <numeric>
using namespace std;
class Solution {
public:
int halveArray(vector<int> &nums) {
// 大根堆,并用 nums 初始化
priority_queue<double, vector<double>, less<double>> heap(begin(nums), end(nums));
// 求和
double sum = accumulate(begin(nums), end(nums), (double) 0);
// 目标值
sum /= 2;
int res = 0;
// 每次找最大值减半,再放回去
for (double minus = 0, half; minus < sum; res++, minus += half) {
half = heap.top() / 2;
heap.pop();
heap.emplace(half);
}
return res;
}
};