持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
hi, 我是小黄瓜没有刺。一枚菜鸟瓜🥒,期待关注➕ 点赞,共同成长~
leetcode链表系列第四篇!🎊
题目 👾
143. 重排链表
给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4]
输出:[1,4,2,3]
示例 2:
输入:head = [1,2,3,4,5]
输出:[1,5,2,4,3]
提示:
- 链表的长度范围为
[1, 5 * 104] 1 <= node.val <= 1000
思路 ✨
- 找到链表的中间值
let len = 0
// 计算链表的长度
for (let p = head; p !== null; p = p.next) {
len++;
}
// 计算中间值
let midNum = len >> 1;
// js中的>>表示有符号位移,当操作一个正数时候:
10 >> 1
// 结果: 5
// 因为10的二进制是1010,往右移动一位就是101,十进制中代表的是5.
- 从中间的值将链表分为左右两个链表
只需要找到左链表的最后一个节点,然后赋值为
null断开连接
let nxt = cur.next
cur.next = null
- 反转右边的链表
while(prev !== fast && cur) {
let nxt = cur.next
cur.next = prev
prev = cur
cur = nxt
}
- 分别从两边链表取值,先取左边的链表再取右边链表
解答 🎉
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {void} Do not return anything, modify head in-place instead.
*/
var reorderList = function(head) {
let len = 0
// 取链表的总长度
for (let p = head; p !== null; p = p.next) {
len++;
}
// 取中间值
let midNum = len >> 1;
// 定义左右指针,此时初始值都赋值为头节点
let fast = head, slow = head;
// 将右指针移动到需要截取的右链表位置
for (let i = 0; i < midNum; i++) {
fast = fast.next;
}
// 移动左指针,将左指针移动到右链表的上一个节点
while(fast.next !== null) {
fast = fast.next
slow = slow.next
}
let prev, cur = slow
// 保存右链表
let nxt = cur.next
// 断开连接,分为左右两个节点 head 和 nxt
cur.next = null
cur = nxt
// 反转右链表
while(prev !== fast && cur) {
let nxt = cur.next
cur.next = prev
prev = cur
cur = nxt
}
// 交叉放置左右各个节点,prev为右链表第一个节点
while(prev) {
let h_node = head.next
head.next = prev
head = h_node
let p_node = prev.next
prev.next = head
prev = p_node
}
return head
}
写在最后 ⛳
leetcode系列第四篇!未来可能会更新实现mini-vue3和javascript基础知识系列,希望能一直坚持下去,期待多多点赞🤗🤗,一起进步!🥳🥳