前言
前面我们整完了几道环形链表相关的题,今天我们来搞反转链表,刚接触可能容易被指针指晕哦! 我们先打个反转链表的基础底,后面我们所有关于反转和节点交换等都是基于此哦!
看题描述
反转链表1 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例 1:
输入: head = [1,2,3,4,5]
输出: [5,4,3,2,1]
整理思路
由上图我们能够得出以下结论:
- 原链表的头节点变成了新链表的尾节点,头节点后的每个节点依次成为了新链表的倒数第2、3、4...个节点
- 那么我们定义一个指针pre,让原链表从头节点开始依次成为pre的
倒数第1,2,3...个节点,最后返回pre即可得到我们的新链表 - 那么如何实现呢?我们从下面的4张图加入指针解析下:
- 图1: 我们首先定义pre指针指向null,cur指向头节点head
- 图2: 因为我们只能一个节点一个节点的往pre指针上添加反转后的节点,所以先反cur,那么我们反之前
先定义next指针用来存cur.next及后面的节点, - 图3、4: 让cur指向的head连接pre指向的null,即cur.next = pre(pre是前项节点的代表,用后项cur连接前项),接着让我们的pre指针指向cur就形成了pre => cur => null(3)、pre => cur => head => null,这样一直反转下去就能得到我们的新链表
开始解题
var reverseList = function(head) {
if(!head) return null;
let pre = null, cur = head;
while(cur) {
let next = cur.next; // 保存后项节点
cur.next = pre; // 当前遍历节点指向后项目节点
pre = cur; // 让cur所指节点成为pre的反转节点
cur = next;
}
return pre;
};
趁热打铁-开始反转链表2
反转链表2 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
输入: head = [1,2,3,4,5], left = 2, right = 4
输出: [1,4,3,2,5]
题目解析
- 此道题目要我们反转链表从left到right处的节点
- 首先我们得让指针跑到反转起点,然后反转
right-left+1个节点即可 - 本题可以利用虚拟头节点做下,一般在头节点会发生变化的情况下使用效果比较好,这样返回虚头ret.next就能拿到我们的新链表而不用担心头节点的问题
开始解题
var reverseBetween = function(head, left, right) {
if(!head) return null;
let ret = new ListNode(-1,head), pre = ret, cnt = right-left+1; //利用虚头
while(--left) { // 先让pre跑到left前一个节点
pre = pre.next;
}
pre.next = getReverse(pre.next,cnt); // 用反转起点前的pre连接反转后的链表节点
return ret.next;
};
var getReverse = function(head,n) {
let pre = null,cur = head;
while(n--) { // 循环n次即反转n个节点
[cur.next,pre,cur] = [pre, cur,cur.next]; // 利用结构赋值简化反转链表1的处理方式
}
head.next = cur; // 因为反转后的尾节点是反转起点head,cur指针指向反转后的尾节点的下一个节点(cur=cur.next循环体最后依次执行)
return pre;
}