206反转链表(4)

142 阅读2分钟

这个题我之前写过,上次船长怎么讲的也完全忘记了,我先按照我自己的记忆,写代码,在分析

image.png 这个距离上次写应该也有一个多月了,完全忘记了,直接的反转需要借助一个头部指针,然后就while循环里面的逻辑,记不清楚,去看了看船长的视频,在看看有没有之前的思路,发现船长的视频是递归写的 而我这个思路是动态规划 只能去看之前自己写的

image.png

方法一 迭代

var reverseList = function(head) {
    if(!head) return head;
    // 定义一个空节点
    let pre = null;
    let cur = head;
    while(cur) {
     // 储存一下cur。next,最后一步使用, ⚠️下面3个步骤不能颠倒 否则不生效
    let n = cur.next;
    //  1 把pre赋值给 cur。next
     cur.next = pre;
    // 2 把当前节点cur 赋值给 pre
     pre = cur;
    // 3 把最开始储存的 cur.next 赋值个cur
     cur = n;
     
     // 这个是简化上面三个步骤,赋值顺序也必须按照上面1,2,3 
     //  [cur.next, pre, cur] =  [pre, cur, cur.next]
    }
    return pre;
};

上面把正确的代码也记录下,上面这些,下出来看也不负责,自己就是写不出来,还是不理解啊,死记硬背 多一段时间还是会忘记.

方法二 递归

递归的思路我记得我之前写过,但是没有找到答案,就看了题解,感觉好理解一点儿..

递归一

var reverseList = function(head) {
    // head.next 不判空 下面 head.next.next = head;会报错, head.next为空 说明只有一个节点 没有必有反转 递归写法也就是递归的反转条件
    if(!head || head.next == null) return head;
    // 递归都是要 先写返回的值 然后在写处理逻辑
    // 1 这一步不定义cur 变量 而是直接返回 reverseList(head.next)是不对的 就相当于先走逻辑 最后返回值 反正不太理解 先记着
   // 简单看成 1 - 2 - 3
    const cur = reverseList(head.next); // 这一步相当于递归的递 返回的是已经反转过的
    // 2 处理逻辑 ; 
    head.next.next = head; // 这一步就是反转(相当于把3指向1,仔细想想 不太对 但是又大概能理解)
    head.next = null; // 掐断
    return cur;
};

这个递归是我之前写的一直参考的 跟船长讲的不一样,我把船长写的c++ 翻译成 js来写如下,提交也对

递归二

var reverseList = function(head) {
    // head.next 不判空 下面 head.next.next = head;会报错, head.next为空 说明只有一个节点 没有必有反转 递归写法也就是递归的反转条件
    if(!head || head.next == null) return head;
     const tail = head.next;
     const p = reverseList(tail);
     // 逻辑在这儿 这两部实现了反转
     head.next = tail.next; // 这一步 去掉tail 是 head.next = head.next.next
     tail.next = head; // 这一步 去掉tail 是 head.next.next = head
     
     // 直接这样写倒是不对
     //  head.next = head.next.next;
     //  head.next.next = head;

    return p;
};