剑指 Offer 24. 反转链表

432 阅读2分钟

剑指 Offer 24. 反转链表

题意

剑指 Offer 24. 反转链表

image.png

解法

1. 三指针(双指针)

大概的思路是对于三个连续的节点A->B->C,用三个指针pre,p,tep一一对应。

  1. 断开B -> C,连接B -> A (此时链表被一分为二,不过 C 节点所在的第二条链表还有tep指针指向,不至于丢失)。
  2. 然后三个指针都向右移动一个节点,因为tep是最前面的节点,所以需要判断是否为空,不为空则前移。
  3. 重复第一步。
  4. p为空时退出循环。
  5. 原来的head节点的next还指向第二个节点,这里要修改。

这个方法的本质就是将后一个节点重新指向前一个节点实现反转,tep的作用是为了保存剩余节点组成的第二个链表不丢失,依次将第二个链表的值加入第一个链表。

2. 递归

leetcode大佬的一种解法,详情点击# 【反转链表】:双指针,递归,妖魔化的双指针

  1. 首先通过递归找到最后一个元素 head.next === null
  2. 每次函数在返回的过程中,让当前结点的下一个结点的 next 指针指向当前节点。
  3. 同时让当前结点的 next 指针指向 NULL ,从而实现从链表尾部开始的局部反转。

注意

  1. 这里一旦找到最后一个节点res后,就不会修改res了,只会层层返回res

3. 妖魔化的双指针

leetcode大佬的一种解法,详情点击# 【反转链表】:双指针,递归,妖魔化的双指针

和双指针的思路有相似之处,区别在于怎么记录未反转链表的位置。

代码

1. 三指针(双指针)

/**
 * Definition for singly-linked list.
 * function ListNode(val) {
 *     this.val = val;
 *     this.next = null;
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var reverseList = function(head) {
    if(!head)return null
    if(!head.next)return head
    let pre = head
    let p = head.next
    let tep = head.next.next
    while(p){
        p.next = pre
        pre = p
        p = tep
        if(tep)tep = tep.next
        
    }
    head.next = null
    return pre
};

2. 递归

var reverseList = function(head) {
    if(head === null||head.next === null){
        return head
    }
    let res = reverseList(head.next)
    head.next.next = head
    head.next = null
    return res
};

3. 妖魔化的双指针

var reverseList = function(head) {
    if(head === null) return null
    let p = head
    while(head.next !== null){
        let tep = head.next.next
        head.next.next = p
        p = head.next
        head.next = tep
    }
    return p
};