[143] 重排链表(38)

79 阅读2分钟

这道题,能看懂,也有思路如下图, 首先贴一下 反转连表的思路 第n次整理以后

image.png

方法一

image.png 后来看了解析,我的思路是对的,但是代码不会写,所以比这瞧一遍,到反转连表这块儿,还是不会写,哎,这个翻转连表最开始就写,写了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] 
};

力扣本题传送门