一、反转链表
题目
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
思路
创建虚拟头结点,作为反转后的最后一个节点指向的空节点。再两两改变节点间指针指向。
代码
struct ListNode* reverseList(struct ListNode* head) {
struct ListNode* pre= NULL; //虚拟头结点,总之遇到链表创建一个虚拟头结点大概都是对的
struct ListNode* temp; //临时节点,用于记录正在操作的节点的下一个节点,因为操作完指针指向了上一个节点,此时无法查询到下一个节点,因次临时保存下一个节点便于后续操作
(双指针法)
while(head){
temp = head -> next;
head -> next = pre; //改变指针指向
pre = head;
head = temp; //继续遍历
}
return pre;
}
(递归法)
struct ListNode* reverse(struct ListNode* pre, struct ListNode* cur) {
if(!cur)
return pre;
struct ListNode* temp = cur->next;
cur->next = pre;
//将cur作为pre传入下一层
//将temp作为cur传入下一层,改变其指针指向当前cur
return reverse(cur, temp);
}
struct ListNode* reverseList(struct ListNode* head){
return reverse(NULL, head);
}
总结
1.临时指针temp,因为1->2->3,变成1<-2 3,此时3无法被使用,所以要存一个“2->”,令之后的3被临时指针指着;
2.核心是双指针,head与pre的交换;
2.这题还有高级解法(递归法),但还不是很看得懂,代码先放这儿,之后再研究研究
二、交换链表节点
题目
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)
思路
类似于上一题,要注意交换顺序
代码
struct ListNode* swapPairs(struct ListNode* head) {
//递归结束条件:头节点不存在或头节点的下一个节点不存在。此时不需要交换,直接返回head
if(!head || !head->next)
return head;
//创建一个节点指针类型保存头结点下一个节点
struct ListNode *newHead = head->next;
//更改头结点+2位节点后的值,并将头结点的next指针指向这个更改过的list
head->next = swapPairs(newHead->next);
//将新的头结点的next指针指向老的头节点
newHead->next = head;
return newHead;
}
以下为后来补充的更易理解版本:
总结
1.看似是两两交换,实际每次交换都要对四个节点做操作;
2.做链表题最好画图理解,不然容易弄乱顺序;
1 -> 2 -> 3 -> 4
①1 -> 3
②3 -> 2
③2 -> 4
1 -> 3 -> 2 ->4
3.注意不能对空指针操作(遍历);