|
| 1 | +# [2674. Split a Circular Linked List](https://leetcode.cn/problems/split-a-circular-linked-list) |
| 2 | + |
| 3 | +[English Version](/solution/2600-2699/2674.Split%20a%20Circular%20Linked%20List/README_EN.md) |
| 4 | + |
| 5 | +## 题目描述 |
| 6 | + |
| 7 | +<!-- 这里写题目描述 --> |
| 8 | + |
| 9 | +<p>Given a <strong>circular linked list</strong> <code>list</code> of positive integers, your task is to split it into 2 <strong>circular linked lists</strong> so that the first one contains the <strong>first half</strong> of the nodes in <code>list</code> (exactly <code>ceil(list.length / 2)</code> nodes) in the same order they appeared in <code>list</code>, and the second one contains <strong>the rest</strong> of the nodes in <code>list</code> in the same order they appeared in <code>list</code>.</p> |
| 10 | + |
| 11 | +<p>Return <em>an array answer of length 2 in which the first element is a <strong>circular linked list</strong> representing the <strong>first half</strong> and the second element is a <strong>circular linked list</strong> representing the <strong>second half</strong>.</em></p> |
| 12 | + |
| 13 | +<div>A <strong>circular linked list</strong> is a normal linked list with the only difference being that the last node's next node, is the first node.</div> |
| 14 | + |
| 15 | +<p> </p> |
| 16 | +<p><strong class="example">Example 1:</strong></p> |
| 17 | + |
| 18 | +<pre> |
| 19 | +<strong>Input:</strong> nums = [1,5,7] |
| 20 | +<strong>Output:</strong> [[1,5],[7]] |
| 21 | +<strong>Explanation:</strong> The initial list has 3 nodes so the first half would be the first 2 elements since ceil(3 / 2) = 2 and the rest which is 1 node is in the second half. |
| 22 | +</pre> |
| 23 | + |
| 24 | +<p><strong class="example">Example 2:</strong></p> |
| 25 | + |
| 26 | +<pre> |
| 27 | +<strong>Input:</strong> nums = [2,6,1,5] |
| 28 | +<strong>Output:</strong> [[2,6],[1,5]] |
| 29 | +<strong>Explanation:</strong> The initial list has 4 nodes so the first half would be the first 2 elements since ceil(4 / 2) = 2 and the rest which is 2 nodes are in the second half. |
| 30 | +</pre> |
| 31 | + |
| 32 | +<p> </p> |
| 33 | +<p><strong>Constraints:</strong></p> |
| 34 | + |
| 35 | +<ul> |
| 36 | + <li>The number of nodes in <code>list</code> is in the range <code>[2, 10<sup>5</sup>]</code></li> |
| 37 | + <li><code>0 <= Node.val <= 10<sup>9</sup></code></li> |
| 38 | + <li><font face="monospace"><code>LastNode.next = FirstNode</code></font> where <code>LastNode</code> is the last node of the list and <code>FirstNode</code> is the first one</li> |
| 39 | +</ul> |
| 40 | + |
| 41 | +## 解法 |
| 42 | + |
| 43 | +<!-- 这里可写通用的实现逻辑 --> |
| 44 | + |
| 45 | +**方法一:快慢指针** |
| 46 | + |
| 47 | +我们定义两个指针 $a$ 和 $b$,初始时都指向链表的头节点。每次迭代时,$a$ 指针向前移动一步,$b$ 指针向前移动两步,直到 $b$ 指针到达链表的末尾。此时,$a$ 指针指向链表节点数的一半,我们将链表从 $a$ 指针处断开,即可得到两个链表的头节点。 |
| 48 | + |
| 49 | +时间复杂度 $O(n)$,其中 $n$ 是链表的长度。需要遍历链表一次。空间复杂度 $O(1)$。 |
| 50 | + |
| 51 | +<!-- tabs:start --> |
| 52 | + |
| 53 | +### **Python3** |
| 54 | + |
| 55 | +<!-- 这里可写当前语言的特殊实现逻辑 --> |
| 56 | + |
| 57 | +```python |
| 58 | +# Definition for singly-linked list. |
| 59 | +# class ListNode: |
| 60 | +# def __init__(self, val=0, next=None): |
| 61 | +# self.val = val |
| 62 | +# self.next = next |
| 63 | +class Solution: |
| 64 | + def splitCircularLinkedList( |
| 65 | + self, list: Optional[ListNode] |
| 66 | + ) -> List[Optional[ListNode]]: |
| 67 | + a = b = list |
| 68 | + while b.next != list and b.next.next != list: |
| 69 | + a = a.next |
| 70 | + b = b.next.next |
| 71 | + if b.next != list: |
| 72 | + b = b.next |
| 73 | + list2 = a.next |
| 74 | + b.next = list2 |
| 75 | + a.next = list |
| 76 | + return [list, list2] |
| 77 | +``` |
| 78 | + |
| 79 | +### **Java** |
| 80 | + |
| 81 | +<!-- 这里可写当前语言的特殊实现逻辑 --> |
| 82 | + |
| 83 | +```java |
| 84 | +/** |
| 85 | + * Definition for singly-linked list. |
| 86 | + * public class ListNode { |
| 87 | + * int val; |
| 88 | + * ListNode next; |
| 89 | + * ListNode() {} |
| 90 | + * ListNode(int val) { this.val = val; } |
| 91 | + * ListNode(int val, ListNode next) { this.val = val; this.next = next; } |
| 92 | + * } |
| 93 | + */ |
| 94 | +class Solution { |
| 95 | + public ListNode[] splitCircularLinkedList(ListNode list) { |
| 96 | + ListNode a = list, b = list; |
| 97 | + while (b.next != list && b.next.next != list) { |
| 98 | + a = a.next; |
| 99 | + b = b.next.next; |
| 100 | + } |
| 101 | + if (b.next != list) { |
| 102 | + b = b.next; |
| 103 | + } |
| 104 | + ListNode list2 = a.next; |
| 105 | + b.next = list2; |
| 106 | + a.next = list; |
| 107 | + return new ListNode[] {list, list2}; |
| 108 | + } |
| 109 | +} |
| 110 | +``` |
| 111 | + |
| 112 | +### **C++** |
| 113 | + |
| 114 | +```cpp |
| 115 | +/** |
| 116 | + * Definition for singly-linked list. |
| 117 | + * struct ListNode { |
| 118 | + * int val; |
| 119 | + * ListNode *next; |
| 120 | + * ListNode() : val(0), next(nullptr) {} |
| 121 | + * ListNode(int x) : val(x), next(nullptr) {} |
| 122 | + * ListNode(int x, ListNode *next) : val(x), next(next) {} |
| 123 | + * }; |
| 124 | + */ |
| 125 | +class Solution { |
| 126 | +public: |
| 127 | + vector<ListNode*> splitCircularLinkedList(ListNode* list) { |
| 128 | + ListNode* a = list; |
| 129 | + ListNode* b = list; |
| 130 | + while (b->next != list && b->next->next != list) { |
| 131 | + a = a->next; |
| 132 | + b = b->next->next; |
| 133 | + } |
| 134 | + if (b->next != list) { |
| 135 | + b = b->next; |
| 136 | + } |
| 137 | + ListNode* list2 = a->next; |
| 138 | + b->next = list2; |
| 139 | + a->next = list; |
| 140 | + return {list, list2}; |
| 141 | + } |
| 142 | +}; |
| 143 | +``` |
| 144 | +
|
| 145 | +### **Go** |
| 146 | +
|
| 147 | +```go |
| 148 | +/** |
| 149 | + * Definition for singly-linked list. |
| 150 | + * type ListNode struct { |
| 151 | + * Val int |
| 152 | + * Next *ListNode |
| 153 | + * } |
| 154 | + */ |
| 155 | +func splitCircularLinkedList(list *ListNode) []*ListNode { |
| 156 | + a, b := list, list |
| 157 | + for b.Next != list && b.Next.Next != list { |
| 158 | + a = a.Next |
| 159 | + b = b.Next.Next |
| 160 | + } |
| 161 | + if b.Next != list { |
| 162 | + b = b.Next |
| 163 | + } |
| 164 | + list2 := a.Next |
| 165 | + b.Next = list2 |
| 166 | + a.Next = list |
| 167 | + return []*ListNode{list, list2} |
| 168 | +} |
| 169 | +``` |
| 170 | + |
| 171 | +### **TypeScript** |
| 172 | + |
| 173 | +```ts |
| 174 | +/** |
| 175 | + * Definition for singly-linked list. |
| 176 | + * class ListNode { |
| 177 | + * val: number |
| 178 | + * next: ListNode | null |
| 179 | + * constructor(val?: number, next?: ListNode | null) { |
| 180 | + * this.val = (val===undefined ? 0 : val) |
| 181 | + * this.next = (next===undefined ? null : next) |
| 182 | + * } |
| 183 | + * } |
| 184 | + */ |
| 185 | + |
| 186 | +function splitCircularLinkedList( |
| 187 | + list: ListNode | null, |
| 188 | +): Array<ListNode | null> { |
| 189 | + let a = list; |
| 190 | + let b = list; |
| 191 | + while (b.next !== list && b.next.next !== list) { |
| 192 | + a = a.next; |
| 193 | + b = b.next.next; |
| 194 | + } |
| 195 | + if (b.next !== list) { |
| 196 | + b = b.next; |
| 197 | + } |
| 198 | + const list2 = a.next; |
| 199 | + b.next = list2; |
| 200 | + a.next = list; |
| 201 | + return [list, list2]; |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +### **...** |
| 206 | + |
| 207 | +``` |
| 208 | +
|
| 209 | +``` |
| 210 | + |
| 211 | +<!-- tabs:end --> |
0 commit comments