这个题我之前写过,上次船长怎么讲的也完全忘记了,我先按照我自己的记忆,写代码,在分析
这个距离上次写应该也有一个多月了,完全忘记了,直接的反转需要借助一个头部指针,然后就while循环里面的逻辑,记不清楚,去看了看船长的视频,在看看有没有之前的思路,发现船长的视频是递归写的 而我这个思路是动态规划 只能去看之前自己写的
方法一 迭代
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;
};