【LeetCode】反转链表(双指针&递归)

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

【LeetCode】反转链表(双指针&递归)_第1张图片

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

【LeetCode】反转链表(双指针&递归)_第2张图片

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

有些小伙伴可能在初次接触LeetCode的时候对于代码的return会产生疑问,比如下题明明题目说的是返回一个链表,但是代码却返回的是一个节点,其实:LeetCode不用自己输出的,你只要返回正确的头节点就可以了,系统会自己去判断

但凡涉及到链表的题目,一定要在纸上把过程先画出来,再写程序,因为有的时候这种操作比较抽象,画出来就比较直观

方法一:双指针

  • 首先定义两个指针,pre和cur,其中pre在cur之后
  • 然后让pre的next指向cur,实现一个局部的反转
  • 然后两个指针同时往后移动一个单位的距离
  • 直到pre走到链表的尾部
/**
 * 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=NULL,*pre=head;
       while(pre!=NULL){
           ListNode* temp=pre->next;
           pre->next=cur;
           cur=pre;
           pre=temp;
       }
       return cur;
    }
};

方法二:递归

  • 首先递归到链表的最后一个节点,该节点就是反转后的头结点
  • 此后每次函数在返回的过程中,让当前节点的下一个节点的next指针指向当前节点
  • 同时让当前节点的next指针指向NULL,从而实现链表尾部开始的局部反转
  • 等到递归函数全部出栈后,链表就反转完成了
  • 注意:head的下一个节点必须为空,不然链表中可能会产生环

递归可能比较难理解,下面贴出一位大佬细致的分析,我也是看了才明白

第一轮出栈,head5head.next为空,返回5
            第二轮出栈,head4head.next5,执行head.next.next=head也就是5.next=4,
                      把当前节点的子节点的子节点指向当前节点
                      此时链表为1->2->3->4<->5,由于45互相指向,所以此处要断开4.next=null
                      此时链表为1->2->3->4<-5
                      返回节点5
            第三轮出栈,head3head.next4,执行head.next.next=head也就是4.next=3,
                      此时链表为1->2->3<->4<-5,由于34互相指向,所以此处要断开3.next=null
                      此时链表为1->2->3<-4<-5
                      返回节点5
            第四轮出栈,head2head.next3,执行head.next.next=head也就是3.next=2,
                      此时链表为1->2<->3<-4<-5,由于23互相指向,所以此处要断开2.next=null
                      此时链表为1->2<-3<-4<-5
                      返回节点5
            第五轮出栈,head1head.next2,执行head.next.next=head也就是2.next=1,
                      此时链表为1<->2<-3<-4<-5,由于12互相指向,所以此处要断开1.next=null
                      此时链表为1<-2<-3<-4<-5
                      返回节点5
            出栈完成,最终头节点5->4->3->2->1

实现代码:

/**
 * 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) {
      if(head==NULL||head->next==NULL){
          return head;
      }
      ListNode* ans=reverseList(head->next);
      head->next->next=head;
      head->next=NULL;
      return ans;
    }
};
生活坏到一定程度就会好起来,因为他无法更坏,努力过后才知道许多事情,坚持坚持就过来了

【LeetCode】反转链表(双指针&递归)_第3张图片

你可能感兴趣的:(LeetCode,leetcode,算法)