一、合并两个有序链表
常规思路:双指针,判断结点大小。
Node *MergeTwoList(Node *head1, Node *head2) {
Node *i = head1->next;
Node *j = head2->next;
Node *nhead = new Node(-1);
Node *k = nhead;
while(i != nullptr && j != nullptr) {
if(i->val <= j->val) {
k->next = i;
i = i->next;
k = k->next;
} else if(i->val > j->val) {
k->next = j;
j = j->next;
k = k->next;
}
}
if(i != nullptr) {
k->next = i;
} else {
k->next = j;
}
return nhead;
}
二、合并多个有序链表
2.1 堆(优先队列)
参考合并两个有序链表,可以设置一个堆,将每个链表的第一个结点插入其中;或者将全部结点一股脑插入进去。
注意:这里在使用C++的优先队列(堆)时,遇到了一个问题,如果队列中的元素是自定义指针类型时,重载运算符失效了,无法完成排序工作。具体解决方法见
struct Node {
int val;
Node *next;
Node(int v) {
val = v;
next = nullptr;
}
};
struct NodeCmp {
bool operator ()(Node *a, Node *b){
return a->val > b->val;//最小值优先
}
};
Node *MergeKLists1(vector<Node*> &lists) {
priority_queue <Node*, vector<Node*>, NodeCmp> q;
for (auto node: lists) {
if(node != nullptr) {
q.push(node);
}
}
Node *head = new Node(-1);
Node *cur = head;
while (!q.empty()) {
auto top = q.top(); q.pop();
cur->next = top;
cur = cur->next;
if(top->next) {
q.push(top->next);
}
}
return head;
}
2.2 两两合并
Node *MergeKLists2(vector<Node*> &lists) {
queue<Node*> q;
for(auto node : lists) {
q.push(node);
}
while(q.size() >= 2) {
Node *l1 = q.front(); q.pop();
Node *l2 = q.front(); q.pop();
Node *nlist = MergeTwoList(l1, l2);
q.push(nlist);
}
return q.front();
}