题目如下:
方法一
暴力求解了,想到最直接的方法就是直接对两个链表进行遍历,将所有的数据都直接存下来,然后对这些数据进行排序,根据排序结果构建新的链表并返回结果。
使用C++编程
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
int s[100];
ListNode* temp = l1;
int i=0;
while(temp!=nullptr){
s[i++]=temp->val;
temp = temp->next;
}
temp = l2;
while(temp!=nullptr){
s[i++]=temp->val;
temp = temp->next;
}
if(i!=0){
sort(s,s+i);
ListNode* l = new ListNode(s[0]);
ListNode* t = l;
for(int j=1;j<i;j++){
t->next = new ListNode(s[j]);
t = t->next;
}
return l;
}
else
return nullptr;
}
};
提交结果如下
方法二
因为题目以说明两个链表均按非递减排序,所以设想能否固定一个链表,将另一个链表直接穿插进去,这样经过一次遍历即可完成对整个链表的排序。
两个链表存在以下三种不同的情况:
1)两个链表均非空:将两个链表重新排序;
2)一个链表为空,一个链表非空:直接返回该非空链表;
3)两个链表均空:直接返回空指针。
使用Java编程
写半天写出个错误示例来,说是链表中出现了环的情况,链表的结点真的晕啊,绕来绕去把自己绕进去了,放弃debug了,把错误代码粘在这里了。去看答案学习了。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1!=null && l2!=null){ //情况一: 两个链表均非空
//目标:打碎l2,在l1找合适的位置将l2穿插进去
ListNode t = l1;
while(l2!=null){
int a2 = l2.val;
ListNode start = l2; //l2起点
while(l1.next.next!=null && !(a2>l1.val && a2<l1.next.val))
l1 = l1.next;
//出循环有两种可能的情况1、l1是链表倒数第二个;2、l1到l1的next是l2片段的插入位置
int a1 = l1.next.val;
while(l2.next!=null && l2.next.val<=a1)
l2 = l2.next;
ListNode end = l2; //l2终点
ListNode temp = l1.next;
l1.next = start;
end.next = temp;
l1 = temp;
if(l1.next==null){
l1.next = l2.next;
return t;
}
l2 = l2.next;
}
return t;
}
else if(l1!=null && l2==null){ //情况二:l1非空,l2为空
return l1;
}
else if(l1==null && l2!=null){ //情况三:l1为空,l2非空
return l2;
}
else //情况四:两个链表均空
return null;
}
}
答案一:递归
千算万算忘记了还能递归,其实整个思路很简单,每次比较链表头节点的大小,当有一个链表为空时返回非空的链表。
java编程
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null)
return l2;
else if(l2==null)
return l1;
else if(l1.val<l2.val){
l1.next = mergeTwoLists(l1.next,l2);
return l1;
}
else {
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}
}
提交结果如下
答案二:迭代
看完两个答案后,感觉我之前的思路过于复杂,总感觉将链表完全拆开重组极耗费时空复杂度却忽略了两个链表非递减排列的事实,而且算法是否复杂应该经过具体的复杂度计算衡量,而不是我这样靠感觉判断。其实整体遍历一遍将节点重新排序即可,完全不需要那么复杂的思路。
C++编程
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* prev = new ListNode(-1);
ListNode* ret = prev;
while(l1!=nullptr && l2!=nullptr){
if(l1->val<=l2->val){
prev->next = l1;
l1 = l1->next;
}
else{
prev->next = l2;
l2 = l2->next;
}
prev = prev->next;
}
if(l1 == nullptr)
prev->next = l2;
else
prev->next = l1;
return ret->next;
}
};
运行结果
相比之下,简单的迭代运行结果居然还没有我最开始的暴力求解运行时间短😂