赞
踩
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
示例2:
输入:head = [1,2]
输出:[2,1]
示例3:
输入:head = []
输出:[]
来源:力扣(LeetCode)
这道题就是个十分简单的节点方向操作题,不涉及什么复杂的算法。我们可以通过构造一个带有头结点的链表使用头插法来实现一个新的反向链表。以[1,2,3]为例演示如下
原地迭代修改就是在每次遍历链表时,让当前cur
节点的next
指针指向前一个节点(完成局部倒置)。不过这种局部修改会使得链表断开,所以我们必须在修改当前节点前将其next节点提前保存。在更改引用之前,还需要存储后一个节点。在完成一次迭代倒置之后分别向前移动cur
指针和pre
指针的位置,最后返回新的头指针pre
。其核心代码如下所示
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
我们首先需要明白链表与递归有着天然的亲和性;接下来我们来看反转链表的问题,对于链表来说我们可以将其拆分为两个部分(头节点head
和其他部分),此时的头节点head不需要反转,我们只需要将头节点之后的链表的倒置链表尾部加上头节点head
就完成了总体的倒置。对于头节点之后的局部链表可以进行类似的拆分工作,这样就形成了递归的解法。
递归的思想在于将问题逐步分解。递归通常与栈相关联,这是因为递归本身就是一个逆向的操作,鉴于此我们可以借助递归的逆向操作将链表进行倒置。假设有链表 [1–>2–>3–>4] ,若以经完成部分转向,假设现在处于 [1-->2-->3<--4]
的状态,那么我们此时要处理的就是节点2和3
之间的关系,此时我们就需要让3的next
指向2,2的next
指向3的next
。
我们将具体的递归过程分为以下两个过程:递以及归。
1
就要先处理2
,要处理2
就要先处理3
,以此类推,总之就是要先处理最后一个节点4
。next
为空也就是它是最后一个节点,那么4将会是新的首节点,此时我们回过头处理3,此时基于3将两个节点3和4进行倒置,以此类推逐步进行指针节点指向的节点和其下一个节点的倒置。head == NULL || head->next == NULL)
/** * 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* reverseList(ListNode* head) { ListNode* cur = head; ListNode* pre = new ListNode(); ListNode* temp; while(cur!=nullptr){ temp = cur->next; cur->next = pre->next; pre->next = cur; cur = temp; } cur = pre->next; delete(pre); return cur; } };
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr) {
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == NULL || head->next == NULL){
return head;
}
ListNode* nex = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return nex;
}
};
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。