双指针+模拟
2022/11/20 修改。
设置哑结点 , 设置双指针 l / r l/r l/r , 在遍历时 r r r 始终领先 l l l 两个位置 , 便于交换 。 即 r = l r=l r=l -> n e x t next next -> n e x t next next 。
交换操作如图
第一个链表到第二个链表的箭头变化就是结点交换 ,调整指向必须按照箭头顺序从前往后,或者从后往前。本文 C++ 代码按照从后往前的顺序调整
(从前往后需要中间变量,博主写的时候不想用中间变量)
代码展示
C++
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
auto dummy = new ListNode(-1),l = dummy, r = head;
dummy->next = head;
if(!r) return dummy->next;//头结点为空
r = r->next;
while(r){
l->next->next = r->next;
r->next = l->next;
l->next = r;
r = r->next;
if(!r->next) break;
l=l->next->next;
r=r->next->next;
}
return dummy->next;
}
};
C语言
struct ListNode* swapPairs(struct ListNode* head){
struct ListNode* dummyhead =(struct ListNode*)calloc(1,sizeof(struct ListNode));
dummyhead->next = head;
struct ListNode* temp = dummyhead;
//空链表和单元素链表直接跳出循环
while(temp->next&&temp->next->next){//temp的后两个元素有NULL
struct ListNode *first = temp->next;
struct ListNode *second = temp->next->next;
temp->next = second;//当前指针指向第二个指针
first->next = second->next;//first->next本来指向second,现在让它指向second->next,解除环
second->next = first;//second->next指向first
temp = first;//temp后移两位
}
return dummyhead->next;//返回哑结点的后继,即头结点
}
- 时间复杂度 : O ( n ) O(n) O(n) , n n n 是链表长度, O ( n ) O(n) O(n) 是遍历链表的时间复杂度。
- 空间复杂度: O ( 1 ) O(1) O(1) ,除若干变量占用的常量级空间,没有使用额外的线性空间
下面是原文,记录了博主曾经写C语言遇到的问题和错误。
2022/10/14
操作链表 , 如有不慎 , 可能形成环,造成
T
L
E
TLE
TLE , 访问了
N
U
L
L
NULL
NULL 的
n
e
x
t
next
next ,造成
r
u
n
t
i
m
e
e
r
r
o
r
runtime\ error
runtime error ——
h
e
a
p
b
u
f
f
e
r
o
v
e
r
f
l
o
w
heap\ \ buffer\ overflow
heap buffer overflow 。
这道题用一个哑结点,结点本身不存任何数,只负责指向链表的 h e a d head head 结点,这样做,可以很方便的操作头结点,减少额外的边界判断。
思路:声明 t e m p temp temp 指向当前位置,初始 t e m p temp temp 指向 d u m m y h e a d dummyhead dummyhead 。进入循环,如果 t e m p temp temp -> n e x t next next 和 t e m p temp temp -> n e x t next next -> n e x t next next 有 N U L L NULL NULL ,说明剩余 1 1 1 个结点 , 或者已遍历完成 。跳出循环。
交换操作 : 朴素的
t
e
m
p
temp
temp ->
n
e
x
t
=
s
e
c
o
n
d
next = second
next=second ,
s
e
c
o
n
d
second
second ->
n
e
x
t
=
f
i
r
s
t
next = first
next=first,
提示①
f
i
r
s
t
first
first ->
n
e
x
t
=
s
e
c
o
n
d
next=second
next=second ->
n
e
x
t
next
next ,是为了让
f
i
r
s
t
first
first 指向我们操作的元素之外,也即
t
e
m
p
temp
temp 后的第三个元素,这是为了解除环
提示②
t
e
m
p
=
f
i
r
s
t
temp = first
temp=first ,让
t
e
m
p
temp
temp 后移两位,继续判断后续元素。
AC