“`python
class Solution(object):
def trainningPlan(self, l1, l2):
//初始化一个辅助节点
dummy=ListNode(0)
cur=dummy
//两个链表都非空进行操作,将更小的值加入新链表,并逐步遍历
while l1 and l2:
if l1.val
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def trainningPlan(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
# if not l1 and not l2: return None #这三种情况,都可以归到最后的拼接中
# if not l1: return l2
# if not l2: return l1
p1,p2=l1,l2
# pre= p1 if p1.val<=p2.val else p2
dummyhead=ListNode(-1) #虚拟头节点,不用关注头节点谁先开始
pre=dummyhead
# if pre==p1:
# p1=p1.next
# else:
# p2=p2.next
while p1 and p2: #双方都有节点可比较
if p1.val<=p2.val: #更新
pre.next=p1
p1=p1.next
else:
pre.next=p2
p2=p2.next
pre=pre.next # 无论哪一个,都要更新pre,向前移动!!
# while p1:
# pre.next=p1
# while p2:
# pre.next=p2
pre.next=p1 if p1 else p2 #把剩下的放过来,只用一个next拼接,剩下的已经有序
return dummyhead.next #使用虚拟头节点,模板,返回值
递归法:
只看着当前的两个节点比较
根据大小,参数中移动l1/l2的指针
终止条件:
某一方为空,返回另一个节点
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def trainningPlan(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
if not l1 and not l2: return None
if not l1: return l2
if not l2: return l1
if l1 and l2:
if l1.val<=l2.val:
l1.next=self.trainningPlan(l1.next,l2) # 返回的只是一个当前节点cur
return l1 #返回当前节点
else:
l2.next=self.trainningPlan(l1,l2.next)
return l2
共以下 55 个回答
“`java
//解题思路:伪头节点+新链表
class Solution {
public ListNode trainningPlan(ListNode l1, ListNode l2) {
ListNode f = new ListNode(0);
ListNode cur = f;
while(l1 != null && l2 != null){
if(l1. val < l2. val){ ListNode p = new ListNode(l1.val); cur.next = p; cur = cur.next; l1 = l1.next; } else if(l1.val > l2.val){
ListNode p = new ListNode(l2.val);
cur.next = p;
cur = cur.next;
l2 = l2.next;
}
else{
ListNode p1 = new ListNode(l1.val);
ListNode p2 = new ListNode(l2.val);
cur.next = p1;
cur = cur.next;
cur.next = p2;
cur = cur.next;
l1 = l1.next;
l2 = l2.next;
}
}
if(l1 == null && l2 != null){
cur.next = l2;
}
else if(l2 == null && l1 != null){
cur.next = l1;
}
else{
cur.next = null;
}
return f.next;
}
}
用迭代法
拷贝原链表,不影响原链表的数据
class Solution {
public ListNode trainningPlan(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(-1);
ListNode current = dummy;
}
创建头节点,每一次比较两个链表的值
事件复杂度O(N)
空间复杂度O(1)
“`python
class Solution(object):
def trainningPlan(self, l1, l2):
//初始化一个辅助节点
dummy=ListNode(0)
cur=dummy
//两个链表都非空进行操作,将更小的值加入新链表,并逐步遍历
while l1 and l2:
if l1.val
时间复杂度O(n+m);空间复杂度O(1)
递归法:
时间复杂度:O(n+m) 合并两个链表,需要遍历这两个链表长度
空间复杂度:O(1) 用了额外的1个虚拟头节点
“`java
class Solution {
public ListNode trainningPlan(ListNode l1, ListNode l2) {
if (l1 == null) {
return l2;
} else if (l2 == null) {
return l1;
} else if (l1.val < l2.val) { l1.next = trainningPlan(l1.next, l2); return l1; } else { l2.next = trainningPlan(l1, l2.next); return l2; } } } 时间复杂度:O(n1 + n2) 空间复杂度:O(1)
class Solution {
public ListNode trainningPlan(ListNode l1, ListNode l2) {
ListNode dumhead= new ListNode(1);
ListNode zhizhen=dumhead;
while(l1!=null&&l2!=null) {
if(l1.val<l2.val){
zhizhen.next=l1;
l1=l1.next;
}
else{
zhizhen.next=l2;
l2=l2.next;
}
zhizhen=zhizhen.next;
}
if(l1null){
zhizhen.next=l2;}
else {zhizhen.next=l1;}
return dumhead.next;
}
}
时间复杂度: O(n1 + n2),其中 n1 是 list1 的长度,n2 是 list2 的长度。
空间复杂度: O(1),因为使用了常数额外空间。
时间复杂度: O(n1 + n2),其中 n1 是 list1 的长度,n2 是 list2 的长度。
空间复杂度: O(1),因为使用了常数额外空间。
代码
“`java
25.合并两个的链表
class Solution {
public ListNode trainningPlan(ListNode l1, ListNode l2) {
class Solution {
public ListNode trainningPlan(ListNode l1, ListNode l2) {
ListNode first=l1,second=l2,head=new ListNode(),h=head;
while(first!=null&&second!=null){
if(first.val<=second.val){
head.next=first;
first=first.next;
}else{
head.next=second;
second=second.next;
}
head=head.next;
}
while(first!=null){
head.next=first;
first=first.next;
head=head.next;
}
while(second!=null){
head.next=second;
second=second.next;
head=head.next;
}
return h.next;
}
}
简化:
1. 后续不需要循环,因为是一个链
// 创建一个虚拟头节点,简化链表操作
ListNode* dummy = new ListNode(0);
ListNode* temp = dummy;
时间复杂度 O(m+n), 空间复杂度O(1)
时间复杂度 O(m+n), 空间复杂度O(1)
解题思路
本题可以采用双指针迭代的思路来解决。首先创建一个虚拟头节点(哨兵节点),这样可以统一处理链表头部的逻辑。然后使用两个指针分别遍历两个链表,比较当前两个指针指向的节点值的大小,将较小的节点接入新链表中,并将对应的指针向后移动。这个过程就像是对两串项链进行归并,每次都选择数值较小的珠子串接到新链表上。
当其中一个链表遍历完成后,我们只需要将另一个链表的剩余部分直接接到新链表的末尾即可。这是因为输入的两个链表本身就是有序的,所以未遍历完的部分一定大于已经合并的所有节点,并且它们本身保持着有序性。
复杂度分析
时间复杂度:O(n + m),其中n和m分别是两个链表的长度。我们需要遍历两个链表各一次。
空间复杂度:O(1),只使用了常数个指针变量,没有使用额外的空间。
代码实现
“`c++
class Solution {
public:
ListNode* trainningPlan(ListNode* l1, ListNode* l2) {
// 创建哨兵节点,简化头节点的处理逻辑
ListNode* merge = new ListNode(0);
ListNode* temp = merge;
};
为什么在判断链表是否为空时是判断 while index1, 而不是while index.next
时间复杂度 O(n), 空间复杂度O(1)
双指针 先建立一个新的LL 拿到头 然后位于两个链表上的指针比较值大小 小的就往新的list上塞
随后如果一个走完了另一个还没走完 说明另一个剩下的都比走完的所有值大 然后将其拼接到结果上
因为一开始创建了一个特殊值的头节点0 取结果时记得把他扣掉
time: O(m+n)
space: O(1) 头节点 剩余的都是建立的next
思路
ListNode merge = new ListNode(0);
ListNode temp = merge;//防止空指针异常
创建临时节点,比较L1,L2的值,temp.next指向较小的值,直到链表遍历结束
代码
/**
* 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 trainningPlan(ListNode l1, ListNode l2) {
ListNode merge = new ListNode(0);
ListNode temp = merge;
}
时间复杂度O(m+n)
空间复杂度O(1)
/**
* 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 trainningPlan(ListNode l1, ListNode l2) {
if (l1 null){return l2;}
if (l2 null){return l1;}
ListNode head;
if(l1.val <= l2.val){
head = l1;
l1 = l1.next;
}
else {
head = l2;
l2 = l2.next;
}
ListNode node = head;
while(l1 != null && l2 != null){
if(l1.val <= l2.val){
node.next = l1;
l1 = l1.next;
}
else{
node.next = l2;
l2 = l2.next;
}
node = node.next;
}
node.next = l1 null? l2:l1;
return head;
}
}
时间复杂度O(m+n)
空间复杂度O(1)
时间复杂度:O(n+m),n 和 m 表示两个链表长度
空间复杂度:O(1)
打卡
”’c++
/**val){
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode trainningPlan(ListNode* l1, ListNode* l2) {
ListNode* dum = new ListNode(-1);
ListNode* res = dum;
while(l1 && l2){
if(l1->val
res->next = l1;
l1 = l1->next;
}else{
res->next = l2;
l2 = l2->next;
}
res = res->next;
}
if(l1){
res->next = l1;
}
if(l2){
res->next = l2;
}
return dum->next;
};
”’
用双指针遍历这两个链表
“`c++
ListNode* trainningPlan(ListNode* l1, ListNode* l2) {
ListNode* p1=l1;
ListNode* p2=l2;
ListNode* head=new ListNode(-1,nullptr);
ListNode* ans=head;
while((l1!=nullptr)||(l2!=nullptr)){
if(l1==nullptr){head->next=new ListNode(l2->val);l2=l2->next;head=head->next;continue;}
if(l2==nullptr){head->next=new ListNode(l1->val);l1=l1->next;head=head->next;continue;}
if((l1->val)>(l2->val)){
head->next=new ListNode(l2->val);
l2=l2->next;
}else{
head->next=new ListNode(l1->val);
l1=l1->next;
}
head=head->next;
}
return ans->next;
}
“`
class Solution {
public:
ListNode* trainningPlan(ListNode* l1, ListNode* l2) {
ListNode* pHead = nullptr;
ListNode* pCur = nullptr;
while (l1 != nullptr && l2 != nullptr) {
ListNode* pTmp = nullptr;
if (l1->val > l2->val) {
pTmp = l2;
l2 = l2->next;
} else {
pTmp = l1;
l1 = l1->next;
}
};
时间复杂度O(n)
时间O(n) 空间O(1)
题解
时间Onval){
class Solution {
public:
ListNode* trainningPlan(ListNode* l1, ListNode* l2) {
if (l1 nullptr)
return l2;
if (l2 nullptr)
return l1;
ListNode* l3;
if(l1->val
l3=l1;
l1=l1->next;
}else{
l3=l2;
l2=l2->next;
}
ListNode* cur = l3;
while (l1 != nullptr && l2 != nullptr) {
if (l1->val < l2->val) {
cur->next = l1;
l1 = l1->next;
} else {
};
“`java
/**
* 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 trainningPlan(ListNode l1, ListNode l2) {
ListNode prehead = new ListNode(-1);
}
““java
/**
* 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 trainningPlan(ListNode l1, ListNode l2) {
ListNode p1=l1;
ListNode p2=l2;
ListNode l3=new ListNode(0);
ListNode p3=l3;
}
时间O(n) 空间O(1)
“`c++
class Solution {
public:
ListNode* trainningPlan(ListNode* l1, ListNode* l2) {
ListNode* merge = new ListNode(0);
ListNode* temp = merge;
while(l1 && l2)
{
if(l1->val < l2->val)
{
temp->next = l1;
l1 = l1->next;
}
else
{
temp->next = l2;
l2 = l2->next;
}
temp = temp->next;
};
“`
//跟着地哥现学
//为什么我上传的markdown格式不对啊?本地是可以正常显示的
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode trainningPlan(ListNode* l1, ListNode* l2) {
ListNode p = l1, *q = l2,h;
ListNode new_head;
new_head.next = h;
while(p || q){
if(p && (p->val < q->val || !q)){
ListNode *node = new ListNode(p->val);
h->next = node;
h = h->next;
p = p->next;
}
if(q && (q->val < p->val || !p)){
ListNode *node = new ListNode(q->val);
h->next = node;
h = h->next;
q=q->next;
}
}
return new_head.next->next;
}
};
时间复杂度o(m+n),空间复杂度o(1)
双指针
递归:
Definition for singly-linked list.
class ListNode:
def init(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def trainningPlan(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
if l1 is None:
return l2
elif l2 is None:
return l1
elif l1.val < l2.val:
l1.next = self.trainningPlan(l1.next, l2)
return l1
else:
l2.next = self.trainningPlan(l1, l2.next)
return l2
定义一个前序节点
时间复杂度:O(n)
空间复杂度:O(1)
//go题解
func trainningPlan(l1 *ListNode, l2 *ListNode) *ListNode {
if l1 nil {
return l2
}
if l2 nil {
return l1
}
}
class Solution {
public:
ListNode* trainningPlan(ListNode* l1, ListNode* l2) {
};
思路:设一个头结点,每次比较l1与l2当前指针所指的值,将小的节点接到头结点中,同时指针移动;最后会有一个链表没有全部比较完,因为题目写的有序,所以直接接在结果链表的后面即可,返回值取头结点的下一位。
时间复杂度O(n+m),空间复杂度O(1)
a.思路分析
1.定义一个虚拟节点,用于改善程序逻辑。
2.当l1和l2指针均不为nullptr时,将较小的节点赋给虚拟节点下一个,并且指针向下移动一位。
3.判断l1和l2不空的那个,将其赋值给虚拟节点
4.返回虚拟节点的下一个,保证输入输出的有效性。
b.代码
时间o(n),空间o(1)
后面写麻烦了,直接等于剩余的l1或l2所指的指针就可以了
/**
* 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 trainningPlan(ListNode l1, ListNode l2) {
ListNode merged = new ListNode();
ListNode head = merged;
if(l1 null && l2 null){
return null;
}
while(l1 != null && l2 != null){
if(l1.val < l2.val){
merged.next = l1;
merged = merged.next;
l1 = l1.next;
}
else{
merged.next = l2;
merged = merged.next;
l2 = l2.next;
}
}
while(l1 != null){
merged.next = l1;
merged = merged.next;
l1 = l1.next;
}
while(l2 != null){
merged.next = l2;
merged = merged.next;
l2 = l2.next;
}
return head.next;
}
}
Definition for singly-linked list.
class ListNode:
def init(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def trainningPlan(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(1)
cur = dummy
while(l1 or l2):
if l1 and l2:
if l1.val <= l2.val:
cur.next = ListNode(l1.val)
l1 = l1.next
else:
cur.next = ListNode(l2.val)
l2 = l2.next
cur = cur.next
else:
if l1:
cur.next = l1
l1 = None
else:
cur.next = l2
l2 = None
return dummy.next
时间复杂度O(max(m,n))
空间复杂度O(1)
时间o(n)
空间o(1)
class Solution {
public ListNode trainningPlan(ListNode l1, ListNode l2) {
// 定义一个虚拟头节点
ListNode dummy = new ListNode(-1);
ListNode current = dummy;
}
class Solution {
public:
ListNode* trainningPlan(ListNode* l1, ListNode* l2) {
//1.判断空的情况
if(l1 nullptr)
return l2;
if(l2 nullptr)
return l1;
//2.创建保存节点、头节点
ListNode *resHead = new ListNode(-1);
ListNode *pre = resHead;
//3.开始比较
while(l1 != nullptr && l2 != nullptr){
//4.比较l1 l2的大小,并且加到pre后面
if(l1->val > l2->val){
pre->next = l2;
l2 = l2->next;
}else{
pre->next = l1;
l1 = l1->next;
}
//5.pre向后移动
pre = pre->next;
}
};
时间复杂度:O(n+m)
空间复杂度:O(1)
class Solution {
public ListNode trainningPlan(ListNode l1, ListNode l2) {
ListNode dummy=new ListNode(-1) ;
ListNode p1=l1,p2=l2,p=dummy;
while(p1!=null && p2!=null){
if(p1.val<=p2.val){
p.next=p1;
p1=p1.next;
p=p.next;
}else{
p.next=p2;
p2=p2.next;
p=p.next;
}
}
p.next=(p1!=null?p1:p2);
return dummy.next;
}
}
时间O(n),空间o(1)
/**
* 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 trainningPlan(ListNode l1, ListNode l2) {
if(l1null||l2null) return l1null?l2:l1;
else if(l1.val<l2.val){
l1.next=trainningPlan(l1.next,l2);
return l1;
}else {
l2.next=trainningPlan(l1,l2.next);
return l2;
}
}
}
思路:先进行判空并处理,接着递归的添加下一个对应的结点即可。
时间复杂度O(n+m)
空间复杂度O(n+m)
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val=undefined ? 0 : val)
* this.next = (next=undefined ? null : next)
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var trainningPlan = function(l1, l2) {
if(l1 = null) return l2
if(l2 = null) return l1
let dummy = new ListNode()
let cur = dummy
let p1 = l1
let p2 = l2
while(p1 ! null || p2 ! null) {
if(p1 null) {
cur.next = p2
return dummy.next
}
if(p2 null) {
cur.next = p1
return dummy.next
}
if(p1.val <= p2.val) {
cur.next = p1
p1 = p1.next
} else {
cur.next = p2
p2 = p2.next
}
cur = cur.next
}
return dummy.next
};
思路:两个指针分别在两个链表上移动
时间复杂度O(N)
空间复杂度O(1)
归并
/**
* 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 trainningPlan(ListNode l1, ListNode l2) {
ListNode res = new ListNode(), r = res;
while(l1 != null || l2 != null){
if(l1 null || (l2 != null && l2.val <= l1.val)){
r.next = l2;
r = r.next;
l2 = l2.next;
}
else{
r.next = l1;
r = r.next;
l1 = l1.next;
}
}
return res.next;
}
}
class Solution {
public ListNode trainningPlan(ListNode l1, ListNode l2) {
ListNode cur = new ListNode();
ListNode dummyHead = cur;
while(l1 != null && l2 != null){
if(l1.val < l2.val){
cur.next = l1;
l1 = l1.next;
}else{
cur.next = l2;
l2 = l2.next;
}
cur = cur.next;
}
if(l1 null){
cur.next = l2;
}else{
cur.next = l1;
}
return dummyHead.next;
}
}
思路:依次遍历合并,最后判断l1、l2哪个为空就接上另一个
时间:o(n)
空间:o(1)
创建虚拟头节点用于构建新链表,
cur指针用于遍历和构建新链表;使用
while循环判断l1和l2都不为空时,比较它们的节点值大小,小的节点则连接到新链表的后面,并将其对应指针前移,更新cur指针,使其指向新链表的最后一个节点,用于循环和后续连接剩余节点使用。当
l1和l2有一个链表不为空时,退出while循环,此时,将剩余的一个链表连接到新链表的尾部。返回新链表的头节点
dummy.next即可。时间复杂度:O(m + n),遍历了两个链表。
空间复杂度:O(1),使用了常数级的额外空间。