本文已参与「新人创作礼」活动,一起开启掘金创作之路。
今天把面试题背了一部分后,开始做笔试题,这是今天做的两道题,虽然第二道是困难题,但弄清楚第一道题目后,第二道题就好做很多了 1.要合并两个有序链表,需要把两个链表对应节点的值进行比较,首先进行特判,如果第一个节点为空,则可以直接返回第二个节点,反之亦然;
2.想清楚两个节点什么时候不比较值的大小,当其中一个节点为空时,就不用比较了,因此可以用while来写它们循环比较的代码,循环终止条件是两个节点中有一个为空就终止。
3.将剩余的链表节点拼接到新链表节点的下一个节点,如果第一个链表不为空,则当前节点的下一个节点就是剩余节点的第一个节点;如果第二个链表不为空的化,当前节点的下一个节点就是剩余节点的第二个节点
4.拼接好链表之后就可以返回哑节点的下一个节点了,也就是所求答案
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* dummy = new ListNode(0);
ListNode* cur = dummy;
if(list1 == nullptr) {
return list2;
}
if(list2 == nullptr) {
return list1;
}
while(list1 && list2) {
if(list1->val < list2->val) {
cur->next = list1;
cur = cur->next;
list1 = list1->next;
}else {
cur->next = list2;
cur = cur->next;
list2 = list2->next;
}
}
if(list1) {
cur->next = list1;
}
if(list2) {
cur->next = list2;
}
return dummy->next;
}
};
做完第一道题之后,第二道题的解题方法是类似的,我们只需要把多个链表两两递归合并,最后合成一个链表即可,所用的思想是分治。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* first, ListNode* second) {
if(first == nullptr) return second;
if(second == nullptr) return first;
ListNode* dummy = new ListNode(0);
ListNode* cur = dummy;
while(first && second) {
if(first->val < second->val) {
cur->next = first;
first = first->next;
}else {
cur->next = second;
second = second->next;
}
cur = cur->next;
}
if(first) {
cur->next = first;
}else {
cur->next = second;
}
return dummy->next;
}
ListNode* merge(vector<ListNode*>& lists, int left, int right) {
if(left == right) return lists[left];
//等同于(right + left) / 2,但可以防止溢出
int mid = left + ((right - left) / 2);
return mergeTwoLists(merge(lists, left, mid), merge(lists, mid + 1, right));
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size() == 0) return nullptr;
return merge(lists, 0, lists.size() - 1);
}
};