题目:206. 反转链表
难度: 简单
题目:
反转一个单链表。
示例
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-linked-list/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
(1)反转链表,可以采用头插法的思想,将每个元素从头到尾依次遍历,每次都将元素插入到头部,从而将链表反转。其实就是迭代法,如:1->2->3 变成 1<-2<-3, 只需要将每个元素的next指针指向前一个元素,从而整个链表就反转了。
(2)递归法。递归法的核心就是在递归的最后一层不断往前反转链表。如链表:1 2 3 4 5,那么递归到最后一个结点5时,当前结点也就是4的下一个结点就是5,那么4-next=5,4->next->next = 5->next。所以,只要4->next->next = 4,就将链表反转了。同时返回新的头也就是5的位置,就如此递归返回,就完成了链表反转,同时反转后的头也找到了。总之,递归法实际上,就是在递归返回的过程中反转链表,并一直返回反转后的头。
解题代码
(1)迭代法
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *pre = NULL;//因为该链表是不带头结点的,所以第一个元素也要,因此第一个元素的前驱为NULL
ListNode *p = head;
while(p != NULL)
{
ListNode *next = p->next;//保存当前位置的下一个元素
p->next = pre;//指向前一个元素
pre = p;//后一个结点的前驱为当前结点
p = next;//使用之前存储的下一个元素
}
return pre;//链表已经反转,最后一个结点为头
}
};
(2)递归法
class Solution {
public:
ListNode* reverseList(ListNode* head) {
//如果为最后一个元素,则递归的最后一层返回
if(!head || !head->next)
return head;
ListNode *newHead = reverseList(head->next);//递归,取下一个元素
//递归返回,
head->next->next = head;//假设是递归的最后一层,那么是最后元素,此时head为倒数第二个元素,head->next为最后一个元素,最后一个元素的next为倒数第二个元素,从而反向两端元素
head->next = nullptr;//因为到第一层时下个元素为空,所以在此设置
return newHead;//newHead在head=最后一个元素时返回,也就是说此时head为最后一个结点,也就是反转链表的头结点
}
};
解题感悟
解决链表反转问题,要对于链表的增删改查十分熟悉,然后才能再次基础上解决问题。同时,画图!!!画图非常关键,画图可以非常直观地看出变换的思路,没有思路的时候通过画图慢慢分析就能理解其中真谛。