合并两个有序链表是二刷,之前牛客网写过,也有博客。
新建节点:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode * pHead = new ListNode(-1); // 最后抛弃这个节点
ListNode * pNode = pHead;
ListNode * pNew;
ListNode* pNode1 = l1, * pNode2 = l2;
while(pNode1 != nullptr && pNode2 != nullptr) {
if(pNode1->val < pNode2->val) {
pNew = new ListNode(pNode1->val);
pNode1 = pNode1->next;
} else {
pNew = new ListNode(pNode2->val);
pNode2= pNode2->next;
}
pNode->next = pNew;
pNode = pNode->next;
}
while(pNode1 != nullptr || pNode2 != nullptr) {
if(pNode1 != nullptr) {
pNew = new ListNode(pNode1->val);
pNode1 = pNode1->next;
} else {
pNew = new ListNode(pNode2->val);
pNode2 = pNode2->next;
}
pNode->next = pNew;
pNode = pNode->next;
}
return pHead->next;
}
};
借鉴了归并算法,并且创建了一个辅助头节点。
仅改变指针
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1 == nullptr) return l2;
if(l2 == nullptr) return l1;
ListNode* pHead;
if(l1->val < l2->val) {
pHead = l1;
pHead->next = mergeTwoLists(l1->next, l2);
} else {
pHead = l2;
pHead->next = mergeTwoLists(l1, l2->next);
}
return pHead;
}
};
时间和空间都达到了优于100%。
接下来合并k个链表,Solution方法1暴力解法,先把所有链表遍历,把出现的值存下来,排序,然后创建节点。
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
vector<int> vals;
int size = lists.size();
for(int i=0; i<size; i++) {
ListNode* pNode = lists[i];
while(pNode != nullptr) {
vals.push_back(pNode->val);
pNode = pNode->next;
}
}
int length = vals.size();
if(length == 0) return nullptr;
sort(vals.begin(), vals.end());
ListNode * pHead = new ListNode(vals[0]);
ListNode * pNode = pHead;
for(int i=1; i<length; i++) {
ListNode * pNew = new ListNode(vals[i]);
pNode->next = pNew;
pNode = pNode->next;
}
return pHead;
}
};
这种方法没有利用k个链表都是有序的特点。
Solution4依次合并链表,调用了合并两个有序链表函数mergeTwoLists
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int size = lists.size();
ListNode* pCurrent = nullptr;
for(int i=0; i<size; i++) {
pCurrent = mergeTwoLists(pCurrent, lists[i]);
}
return pCurrent;
}
};
pCurrent必须赋值为nullptr,否则在执行mergeTwoLists报错;
Solution5,二路归并,两两合并:
自己根据归并算法MergeSort函数的经验写的递归:
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
// Solution 5
int size = lists.size();
if(size == 0) return nullptr;
if(size == 1) return lists[0];
int i = 0;
vector<ListNode*> nextLists;
while(i <= size-2) {
nextLists.push_back(mergeTwoLists(lists[i], lists[i+1]));
i += 2;
}
if(i == size-1) {
nextLists.push_back(lists[size-1]);
}
return mergeKLists(nextLists);
}
};
借鉴了别人的博客写:
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
// Solution 5
int size = lists.size();
if(size == 0) return nullptr;
int currentSize = size;
while(currentSize > 1) {
int k = (currentSize + 1) / 2;
for(int i=0; i<currentSize/2; i++) {
lists[i] = mergeTwoLists(lists[i], lists[i+k]);
}
currentSize = k;
}
return lists[0];
}
};
Solution2和3没有实现,还不清楚什么是优先队列。
对了,这是我做的第一道hard题目哈哈,也没那么恐怖,继续努力!