这道题,能看懂,也有思路如下图, 首先贴一下 反转连表的思路 第n次整理以后
方法一
后来看了解析,我的思路是对的,但是代码不会写,所以比这瞧一遍,到反转连表这块儿,还是不会写,哎,这个翻转连表最开始就写,写了n次还是不会
var reorderList = function (head) {
// 设置一个头节点
const pre = new ListNode(0, head);
// 快慢指针分割连标为左右两个
let fast = pre, slow = pre;
while (fast && fast.next) {
// 慢指针走一步
slow = slow.next;
// 快指针走2步
fast = fast.next;
fast = fast.next;
}
let right = slow.next;
slow.next = null;
let left = pre.next;
// 反转右边连标
right = reverse(right);
// 左一个 右一个的拼接
while (left && right) {
let lNext = left.next, rNext = right.next;
// 先拼接后边
right.next = left.next;
left.next = right;
// 为下一步循环复制
left = lNext;
right = rNext;
}
return pre.next;
}
// 反转连标
function reverse(node) {
let pre = null, cur = node;
while (cur) {
// 后面分析的是第一步
let next = cur.next; // 先储存下一个节点 2
// 连表从后往前拼接 null 1->2->3 第一步反转成2-1-null
cur.next = pre; // 此时cur为1 把0拼接到1后面
pre = cur; // 把1给你
cur = next; // 2给1
}
return pre;
}
方法二 最优解
看题解的时候发现有个更好的解决方法,比这瞧一遍
方法二-1(好理解)
var reorderList = function (head) {
// 把连表每一项掐断 放到一个数组里面
let arr = [];
let temp = null;
while (head) {
// 保存head.next的值 为下一轮循环做准备
temp = head.next;
// 掐断
head.next = null;
// 存在数组中
arr.push(head);
// 下一轮做准备
head = temp;
}
// 定义左右指针
let left = 0, right = arr.length - 1;
// 左右指针 拼接
while (left < right) {
// 把右边倒数第一个拼接在左边第一个
arr[left].next = arr[right];
// 防止成环增加判断
if (left + 1 != right) {
// 把左边第二个给右边的,第一轮来说 也就是拼接第三个
arr[right].next = arr[left + 1]
}
// 左右指针想中间移动 准备一个循环
left++;
right--;
}
return arr[0];
}
方法二-2(代码少)
这个思路都是一样,但是代码更少,可以进阶
var reorderList = function(head, s = [], tmp) {// 换行可删除,合并到4行
while (head)
tmp = head.next,
head.next = null,
s.push(head),
head = tmp
var i = -1, j = s.length
while (++i < --j)
s[i].next = s[j],
j !== i + 1 && (s[j].next = s[i + 1])
return s[0]
};