重排链表
This commit is contained in:
48
1.重排链表/复习.js
Normal file
48
1.重排链表/复习.js
Normal file
@ -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
|
||||||
|
};
|
38
1.重排链表/笔记.md
Normal file
38
1.重排链表/笔记.md
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
42
1.重排链表/解1.js
Normal file
42
1.重排链表/解1.js
Normal file
@ -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
|
||||||
|
}
|
37
1.重排链表/题目.md
Normal file
37
1.重排链表/题目.md
Normal file
@ -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`
|
55
1.重排链表/题解.md
Normal file
55
1.重排链表/题解.md
Normal file
@ -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)
|
Reference in New Issue
Block a user