反转链表1
要求
给一个单链表的头节点 head ,反转链表,并返回反转后的链表。
[1,2,3,4] -> [4,3,2,1]
反转链表1思路
null -> 1 -> 2 -> 3 -> 4
空指针pre指向null
cur指向头
定义一个next指向头.next(防止后面的链表丢失)
1、let next = cur.next
null 1 -> 2 -> 3 -> 4 -> null
(pre) (cur) (next)
2、cur.next = pre
null <- 1 2 -> 3 -> 4 -> null
(pre) (cur) (next)
3、pre = cur
null <- 1 2 -> 3 -> 4 -> null
(cur) (next)
(pre)
4、cur = next
null <- 1 2 -> 3 -> 4 -> null
(pre) (next)
(cur)
然后再次while判断,进入循环
1、let next = cur.next
null <- 1 2 -> 3 -> 4 -> null
(pre) (cur) (next)
......
......
重复以上步骤,直到cur指向null,则全部反转完毕
初步尝试
var reverseList = function (head) {
if (!head.length) return head;
let list = [];
while(head.length){
list.push(head[head.length-1]);
head = head.split(0,head.length-1);
}
return list
};
结果:false
当数据是数组的话,使用以上代码是可以实现的,但是,题目要求是链表,链表所具有的特性是”松散“,不可使用下标,所以以上代码说是反转数组更为合适
再次尝试
var reverseList = function (head) {
// 当head为空,直接return
if (!head) return null;
// 定义一个空指针,一个head
let pre = null,
cur = head;
while (cur) {
// 解构赋值写法
[cur.next, pre, cur] = [pre, cur, cur.next]
// let next = cur.next;
// cur.next = pre;
// pre = cur;
// cur = next;
}
return pre
};
结果:true
此处代码实现的思路:反转链表1思路
反转链表2
要求
给单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。
反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
使用 head = 1->2->3->4->5->6->7->8->9 left=6 right=8来举例
思路
当我们需要反转例子链表,达到 head = 1->2->3->4->5->8->7->6->9的结果
可以通过上面的‘反转链表1’来获得灵感:1->2->3->4->5不动,6->7->8反转链表,得到8->7->6,然后再设置指针所指的下一节点,5指向8,6指向9。
代码
代码注释有点多,每行代码都有1到多行的注释,需要的同学可以复制到编辑器里看
var reverseBetween = function (head, left, right) {
// 使用 head = 1->2->3->4->5->6->7->8->9 left=6 right=8 来举例
// 判断传进来的head是否为空,为空直接return
if (!head) return null;
// 在head前再创建一个节点ret,作用?
let ret = new ListNode(-1, head),
// -1(ret) -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9
// 创建一个指针pre,指向我们在head前创建的节点ret
pre = ret,
// -1(ret,pre) -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9
// 计算需要反转的节点数
cnt = right - left + 1;
// cnt = 8-6+1 = 3
// 此处while,使用pre找到需要反转的节点的初始位置
while (--left) {
pre = pre.next;
/**
*
* 第一次
* left=5
* -1(ret) -> 1(pre) -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9
*
* 第二次
* left=4
* -1(ret) -> 1 -> 2(pre) -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9
*
* ......
* ......
*
* 第五次
* left=1
* -1(ret) -> 1 -> 2 -> 3 -> 4 -> 5(pre) -> 6 -> 7 -> 8 -> 9
*
* */
}
// 跳出循环后
// 此时链表的情况为: -1(ret) -> 1 -> 2 -> 3 -> 4 -> 5(pre) -> 6 -> 7 -> 8 -> 9
// 把反转的节点的第二个位置,以及反转的节点数,传入reverse
pre.next = reverse(pre.next, cnt);
/**
* 经过reverse函数的处理,return回来的是:pre.next = 8
* 8 -> 7 -> 6 -> 9
* 即总体的链表为:-1(ret) -> 1 -> 2 -> 3 -> 4 -> 5(pre) -> 8 -> 7 -> 6 -> 9
* */
return ret.next;
// return 1 -> 2 -> 3 -> 4 -> 5(pre) -> 8 -> 7 -> 6 -> 9
};
var reverse = function (head, n) {
// 此处的head是6,n是3
let pre = null,
cur = head;
// cur = 6
// 此处while,每反转一次,n--,直到n==0,
while (n--) {
// 此处解构赋值意思与反转链表.JS相同
[cur.next, pre, cur] = [pre, cur, cur.next]
/**
* 原本链表结构为: 6 -> 7 -> 8 -> 9
*
* 第一次 n=3
* cur.next = pre
* null(pre) <- 6(cur) 7 -> 8 -> 9
*
* pre = cur
* null <- 6(cur,pre) 7 -> 8 -> 9
*
* cur = cur.next
* null <- 6(pre) 7(cur) -> 8 -> 9
*
*
*
* 第二次 n=2
* cur.next = pre
* null <- 6(pre) <- 7(cur) 8 -> 9
*
* pre = cur
* null <- 6 <- 7(cur,pre) 8 -> 9
*
* cur = cur.next
* null <- 6 <- 7(pre) 8(cur) -> 9
*
*
*
* 第三次 n=1
* cur.next = pre
* null <- 6 <- 7(pre) <- 8(cur) 9
*
* pre = cur
* null <- 6 <- 7 <- 8(cur,pre) 9
*
* cur = cur.next
* null <- 6 <- 7 <- 8(pre) 9(cur)
*
* */
}
// 跳出循环后,此时的pre为: 8(pre) -> 7 -> 6 -> null
head.next = cur;
// 6.next = 9
// 即:8(pre) -> 7 -> 6 -> 9
return pre;
// return 8(pre) -> 7 -> 6 -> 9
}