算法之反转链表

41 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情

关于算法系列已更新部分文章,后续会陆续增加内容:

【1】 算法之用动态规划实现斐波那契数列

【2】 算法之双指针法的应用

【3】 算法之链表的含义

【4】 算法之移除链表元素

【5】 算法之字符串的括号匹配

反转链表

题目描述: 提供一个单链表的头节点 head ,请你反转链表,并返回反转后的链表

题目位置: 206. 反转链表

示例:

输入: head = [1,2]

输出: [2,1]

实现思路

首先,不考虑定义新链表实现反转(浪费空间)。

由于链表的结构和性质,修改链表的结构实际就是操作各个节点的 next。

所以在这个过程中,只需要改变链表的next指针的指向,就可以直接将链表反转 ,不需要重新定义新链表

有两种思路可以解决而这个问题:

  • 递归

  • 双指针法

    关于双指针前面有介绍过字符串反转方法的实现

这两种方式都是从前往后翻转指针指向

代码实现

  1. 递归:
var reverse = function(pre, head) {
    if(!head) return pre;
    const temp = head.next;
    head.next = pre;
    pre = head
    return reverse(pre, temp);
}

var reverseList = function(head) {
    return reverse(null, head);
};
  1. 双指针法:
  • 如果头结点不存在或只有一个头节点,返回 head 并结束函数
  • 初始化 cur = head(cur指针指向头结点),pre = NULL
  • cur 用来改变链表的指向,所以需要预先存储cur.next
  • cur.next = pre (指向它的前一个节点,pre初始为空,后面会进行移动)
  • pre 向后移动一位(也就是当前cur的位置)
  • cur向后移动一位(也就是temp的位置,之前预先存储的cur.next)
  • 最后返回 pre 指针,pre指针指向的是原来最后的一个节点,也就是新的头节点
var reverseList = function(head) {
    if(!head || !head.next) return head;
    let temp = null, pre = null, cur = head;
    while(cur) {
        temp = cur.next;
        cur.next = pre;
        pre = cur;
        cur = temp;
    }
    // temp = cur = null;
    return pre;
};

图解:

初始状态:

image.png

到达中间某个节点

image.png

最终状态

image.png