链表之反转链表专题

简介: 链表之反转链表专题

链表之反转链表专题

如题,LeetCode 206

看到反转链表,我们要思考的核心点在于如何让链表的结点指针指向的方向反转

对于反转链表,一般有迭代或者递归两种思考方向

第一种:迭代

在这种方案中,做题总结出了双指针迭代比较高效,同时有一种双指针的迭代公式

具体的动画效果可以参考LeetCode官方题解

题解动画

while(cur!=null) {
  //记录当前节点的下一个节点
  tmp = cur.next;
  //然后将当前节点指向pre
  cur.next = pre;
  //pre和cur节点都前进一位
  pre = cur;
  cur = tmp;
}

比如,在这个题当中,

step1:使用临时节点 tmp 记录当前节点的下一个结点(和我们常用的借用第三个数交换另外两个数的值思想一致)

step2:控制下一个结点的方向反转

step3:移动当前节点和前驱节点

起始状态为下图所示,那么,我们肯定要记录当前节点的下一个结点,我们使用一个临时的指针用于存储达到交换的目的,这里的思想和常用的交换两个数借用第三个数的思想一致。

class Solution {
  public ListNode reverseList(ListNode head) {
    //申请节点,pre和 cur,pre指向null
    ListNode pre = null;
    ListNode cur = head;
    ListNode tmp = null;
    while(cur!=null) {
      //记录当前节点的下一个节点
      tmp = cur.next;
      //然后将当前节点指向pre
      cur.next = pre;
      //pre和cur节点都前进一位
      pre = cur;
      cur = tmp;
    }
    return pre;
  }
}

第二种:递归

首先,我们看到这种题肯定会下意识的思考:

step1: 将头结点先移动到最后

step2: 将节点指针的顺序反过来(在这里还要注意防止循环链表的出现,所以要让head.next = null)

step3: 递归调用,返回当前的结点

class Solution {
  public ListNode reverseList(ListNode head) {
    //递归终止条件是当前为空,或者下一个节点为空
    if(head==null || head.next==null) {
      return head;
    }
    //step1:递归调用,将头结点移动到最后,这里的cur就是最后一个节点
    ListNode cur = reverseList(head.next);
        //step2:控制结点指针方向反转
    //所以head.next.next 此时的head为4的结点,head.next为5的结点,head.next.next指向head就是5->4
    head.next.next = head;
    //此时的head还是为4,如果设置这个的话,那么head.next指向的是5,此时结点4和结点5之间时双向链表,为了防止链表循环,需要将head.next设置为空
    head.next = null;
    //每层递归函数都返回cur,也就是最后一个节点
    return cur;
  }
}

Leetcode 92 反转链表

这个题就更加能让我们弄懂了

迭代的解法

class ListNode{
    int val;
    ListNode listNode;
    public ListNode(int x){
        val = x;
    }
}
public class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        //初始化一个节点值为0的空节点
        ListNode dummy = new ListNode(0);
        //让该结点指向头结点
        dummy.next = head;
        //构建一个prev结点为当前空节点
        ListNode prev = dummy;
        //迭代调用,记录当前prev节点的移动
        while (m > 1) {
            prev = prev.next;
            m--;
            n--;
        }
        //结束上述while循环的条件是prev结点已经指向了要交换的结点的起始结点
        head = prev.next;
        // 这里假设第m个结点到第n个结点以5->3->4为例
        while (n > 1) {
            //next -> 3
            ListNode next = head.next;
            //将头结点下一个结点指向紧挨着头结点的下一个结点的下一个结点 比如 5->3->4 ,此时5->4
            head.next = head.next.next;
            // 3 -> 5
            next.next = prev.next;
            // 此时将第m-1个结点指向 3,这个时候相当于 head -> 3 -> 5 ->4,相当于交换了第m个和第m+1个结点的位置,再迭代,直到n为0
            prev.next = next;
            n--;
        }
        return dummy.next;
    }
}


相关文章
|
7月前
|
索引
【力扣刷题】两数求和、移动零、相交链表、反转链表
【力扣刷题】两数求和、移动零、相交链表、反转链表
50 2
【力扣刷题】两数求和、移动零、相交链表、反转链表
|
算法
【LeetCode力扣】234 快慢指针 | 反转链表 | 还原链表
【LeetCode力扣】234 快慢指针 | 反转链表 | 还原链表
91 0
|
测试技术
【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点
【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点
85 0
【面试必刷TOP101】反转链表 & 链表内指定区间反转
【面试必刷TOP101】反转链表 & 链表内指定区间反转
62 0
【Leetcode -86.分隔链表 -92.反转链表Ⅱ】
【Leetcode -86.分隔链表 -92.反转链表Ⅱ】
45 0
代码随想录Day03 | 链表基础1 LeetCode T203 移除链表元素 T707设计链表 T206 反转链表
代码随想录Day03 | 链表基础1 LeetCode T203 移除链表元素 T707设计链表 T206 反转链表
54 0
|
7月前
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点.
<数据结构>五道LeetCode链表题分析.环形链表,反转链表,合并链表,找中间节点
53 1
|
7月前
|
C++
[leetcode 链表] 反转链表 vs 链表相交
[leetcode 链表] 反转链表 vs 链表相交
|
7月前
|
C语言 C++ 索引
【力扣】141. 环形链表、160. 相交链表、206.反转链表、234. 回文链表
【力扣】141. 环形链表、160. 相交链表、206.反转链表、234. 回文链表
|
7月前
|
C语言
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】
反转链表、链表的中间结点、合并两个有序链表【LeetCode刷题日志】