做了LeetCode21 ,题目的目的是归并两个已经排好序的链表。
思考了一下,解题思路如下:
本题的目的就是将两个排好序的列表重新排序为一个列表
有一点像归并排序的归并阶段
用C++的指针速度应该是比较快的
首先,分别用两个指针指向两个链表的首部
之后比较,将较小值放入新链表中,并且此指针后移,直到有一个指针指向空,之后把非空指针指向的元素及其后面元素全部加到结果链表中
基本代码如下:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
//解决有其中任何一个为空的情况
if (l1 == NULL&&l2 == NULL)
return NULL;
if (l2 == NULL)
return l1;
if (l1 == NULL)
return l2;
//当两个链表都不为空的时候
ListNode *point1 = l1, *point2 = l2,*result,*temp;
//确定链表头
if (point1->val < point2->val){
result = point1;
point1 = point1->next;
}
else{
result = point2;
point2 = point2->next;
}
temp = result;
//构造链表
while (point1!=NULL&&point2!=NULL)
{
if (point1->val < point2->val){
temp->next = point1;
temp = temp->next;
point1 = point1->next;
}
else{
temp->next = point2;
temp = temp->next;
point2 = point2->next;
}
}
if (point1 == NULL&&point2 == NULL)
return result;
if (point2 == NULL){
temp->next = point1;
return result;
}
if (point1 == NULL){
temp->next = point2;
return result;
}
}
};
想了一下,在result赋初值的时候没有必要这么麻烦,做了一点点改进:
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
//解决有其中任何一个为空的情况
if (l1 == NULL&&l2 == NULL)
return NULL;
if (l2 == NULL)
return l1;
if (l1 == NULL)
return l2;
//当两个链表都不为空的时候
ListNode *point1 = l1, *point2 = l2,*result,*temp;
//确定链表头
result = new ListNode(0);
temp = result;
//构造链表
while (point1!=NULL&&point2!=NULL)
{
if (point1->val < point2->val){
temp->next = point1;
temp = temp->next;
point1 = point1->next;
}
else{
temp->next = point2;
temp = temp->next;
point2 = point2->next;
}
}
if (point2 == NULL)
temp->next = point1;
else if (point1 == NULL)
temp->next = point2;
return result->next;
}
};
测试过,速度明显比之前快很多。改进就是先任意设置一个头指针,最后返回的是result的next个元素。
参看其他大神的代码,发现如下解法。
递归求解:
思路是想要找到结果链表中的下一个元素,需要在另一个链表和此链表中的下一个元素中寻找。即将另一个链表中的当前元素和此元素的下一个元素先进行归并操作,在放在这个元素的后面,这就是归并的思路。
代码如下:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (l2 == NULL)
return l1;
if (l1 == NULL)
return l2;
if (l1->val < l2->val){
l1->next = mergeTwoLists(l1->next, l2);
return l1;
}
else{
l2->next = mergeTwoLists(l2->next, l1);
return l2;
}
其他方案都差不多。
这个问题其实就是一个简化版的归并的部分操作。