commit ddf756f53d24748551a00fba43bdbd1bb10c70d1 Author: mol Date: Mon Jul 31 13:57:28 2023 +0800 重排链表 diff --git a/1.重排链表/复习.js b/1.重排链表/复习.js new file mode 100644 index 0000000..5d79e74 --- /dev/null +++ b/1.重排链表/复习.js @@ -0,0 +1,48 @@ +/** + * 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 slow = head + let fast = head + + // 使用快慢指针寻找链表中点 + while (fast.next && fast.next.next) { + fast = fast.next.next + slow = slow.next + } + + // 拆分成前后链表 + let cur = slow.next + slow.next = null + + // 反转后链表 + let pre = null + while (cur) { + let next = cur.next // 4 null + cur.next = pre // null 3 + pre = cur // 3 4 + cur = next // 4 null + // null <- 3 <- 4 + } + + // 合并前后链表 + let lp = head + while (lp && pre) { + let ln = lp.next + let rn = pre.next + lp.next = pre + pre.next = ln + lp = ln + pre = rn + } + + return head +}; \ No newline at end of file diff --git a/1.重排链表/笔记.md b/1.重排链表/笔记.md new file mode 100644 index 0000000..6d5307f --- /dev/null +++ b/1.重排链表/笔记.md @@ -0,0 +1,38 @@ +## 快慢指针 +快慢指针中的快慢指的是移动的步长,即每次向前移动速度的快慢。例如可以让快指针每次沿链表向前移动2,慢指针每次向前移动1次。 + +### 快慢指针的应用 +#### 判断单链表是否为循环链表 +让快慢指针从链表头开始遍历,快指针向前移动两个位置,慢指针向前移动一个位置;如果快指针到达NULL,说明链表以NULL为结尾,不是循环链表。如果 快指针追上慢指针,则表示出现了循环。 +``` +fast=slow=head; +fast=fast->next->next; +slow=slow->next; +while(true){ +if (fast==NULL || fast->next==NULL) +return false; +else if (fast==slow || fast->next==slow) +return true; +else{ +fast=fast->next->next; +slow=slow->next; +} +} +``` +#### 在有序链表中寻找中位数 +该方法在不借助计数器变量实现寻找中位数的功能。原理是:快指针的移动速度是慢指针移动速度的2倍,因此当快指针到达链表尾时,慢指针到达中点。程序还要考虑链表结点个数的奇偶数因素,当快指针移动x次后到达表尾(1+2x),说明链表有奇数个结点,直接返回慢指针指向的数据即可。如果快指针是倒数第二个结点,说明链表结点个数是偶数,这时可以根据“规则”返回上中位数或下中位数或(上中位数+下中位数)的一半。 +``` +while (fast&&slow) +{ +if (fast->next==NULL) +return slow ->data; +else if (fast->next!= NULL && fast->next->next== NULL) +return (slow ->data + slow ->next->data)/2; +else +{ +fast= fast->next; +fast= fast->next; +slow = slow ->next; +} +} +``` \ No newline at end of file diff --git a/1.重排链表/解1.js b/1.重排链表/解1.js new file mode 100644 index 0000000..cb7d064 --- /dev/null +++ b/1.重排链表/解1.js @@ -0,0 +1,42 @@ +/** + * 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) { + const node = head + let lastNode = getLastNode(node) + let currentNode = node + while (!(currentNode === lastNode || currentNode.next === lastNode)) { + const secNode = currentNode.next + const lastPrevNode = getPrevNode(node, lastNode) + currentNode.next = lastNode + lastNode.next = secNode + currentNode = secNode + lastNode = lastPrevNode + lastNode.next = null + } + return head +}; + +function getLastNode(node) { + let lastNode = node; + while (lastNode.next) { + lastNode = lastNode.next + } + return lastNode +} + +function getPrevNode(head, node) { + let currentNode = head; + while (currentNode && currentNode.next !== node) { + currentNode = currentNode.next + } + return currentNode +} \ No newline at end of file diff --git a/1.重排链表/题目.md b/1.重排链表/题目.md new file mode 100644 index 0000000..47f9c40 --- /dev/null +++ b/1.重排链表/题目.md @@ -0,0 +1,37 @@ +给定一个单链表 L 的头节点 head ,单链表 L 表示为: + +``` +L0 → L1 → … → Ln - 1 → Ln +``` +请将其重新排列后变为: + +``` +L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … +``` +不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 + + + +示例 1: + +![1626420311-PkUiGI-image[1].png](https://picbed.hiiragi.club:8081/i/2023/07/31/64c74c89a9ff8.png) + +``` +输入:head = [1,2,3,4] +输出:[1,4,2,3] +``` +示例 2: + +![1626420320-YUiulT-image[1].png](https://picbed.hiiragi.club:8081/i/2023/07/31/64c74c8a1d9a8.png) + +``` +输入:head = [1,2,3,4,5] +输出:[1,5,2,4,3] +``` + + +提示: + +- 链表的长度范围为 `[1, 5 * 104]` + +- `1 <= node.val <= 1000` \ No newline at end of file diff --git a/1.重排链表/题解.md b/1.重排链表/题解.md new file mode 100644 index 0000000..031f363 --- /dev/null +++ b/1.重排链表/题解.md @@ -0,0 +1,55 @@ +方法一:快慢指针 + 反转链表 + 合并链表 + +> 作者:lcbin +链接:https://leetcode.cn/problems/reorder-list/solution/python3javacgo-yi-ti-yi-jie-kuai-man-zhi-t9u2/ +来源:力扣(LeetCode) +著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 +我们先用快慢指针找到链表的中点,然后将链表的后半部分反转,最后将左右两个链表合并。 + +```js +/** + * 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 slow = head; + let fast = head; + while (fast.next && fast.next.next) { + slow = slow.next; + fast = fast.next.next; + } + + // cur 指向右半部分链表 + let cur = slow.next; + slow.next = null; + + // 反转右半部分链表 + let pre = null; + while (cur) { + const t = cur.next; + cur.next = pre; + pre = cur; + cur = t; + } + cur = head; + + // 此时 cur, pre 分别指向链表左右两半的第一个节点 + // 合并 + while (pre) { + const t = pre.next; + pre.next = cur.next; + cur.next = pre; + cur = pre.next; + pre = t; + } +}; +``` +时间复杂度O(n),其中 n 是链表的长度。空间复杂度O(1) \ No newline at end of file