Runner 技术组合两个相等的链表
Runner technique to combine two equal Linked Lists
所以,我在这里面临一个疑问。
我正在阅读《破解编码面试》一书。下面的文字写在那里。
假设你有一个链表 a1->a2....->an->b1->b2....bn
,你想将它重新排列成 a1->b1->a2->b2->.....an->bn
。你不知道链表的长度,但你只知道它是一个偶数。
(这里两个链表长度相同)
您可以让一个指针 p1(快速指针)每两个元素移动一次 p2 移动一次。当 p1 到达链表的末尾时,p2 将位于端点。然后,将 p1 移回前面并开始 "weaving" 个元素。在每次迭代中,p2 选择一个元素并将其插入到 p1 之后。
我不明白当p1 到达链表末尾时,p2 会在中点。如果 n=3(长度 = 6),这就是我的想象。下面的每个步骤代表一次迭代。
1. a1 (p1, p2)->a2->a3->b1->b2->b3
2. a1->a2 (p2)->a3 (p1)->b1->b2->b3
3. a1->a2->a3 (p2)->b1->b2 (p1)->b3
4. Index out of bounds error because p2 now points to a node after b3.
我是不是走错地方了?
从第二个位置开始 p2。
a1(p1)-> a2 (p2) -> a3 -> a4 -> b1 -> b2 -> b3 -> b4
a1-> a2 (p1) -> a3 -> a4 (p2)-> b1 -> b2 -> b3 -> b4
a1-> a2 -> a3(p1) -> a4 -> b1 -> b2(p2) -> b3 -> b4
a1-> a2 -> a3 -> a4(p1) -> b1 -> b2 -> b3 -> b4(p2)
让n = 2
。我们从一个列表开始:
a1 -> a2 -> b1 -> b2
令p1
成为一个"fast"指针,最初指向head的后继者。
让 p2
成为一个 "slow" 指针,最初指向头部。
p1
a1 -> a2 -> b1 -> b2
p2
我们将 p1
移动两位,将 p2
移动一位,直到 p1
到达列表的末尾(没有下一个)。
p1
a1 -> a2 -> b1 -> b2
p2
将p1
移回头部。
p1
a1 -> a2 -> b1 -> b2
p2
前进 p2
.
p1
a1 -> a2 -> b1 -> b2
p2
"Weaving" 开始。
将p2
指向的元素移到p1
之后。在插入元素后前进 p1
。
p1
a1 -> b1 -> a2 -> b2
p2
将p2
指向的元素移到p1
之后。在插入元素后前进 p1
。
p1
a1 -> b1 -> a2 -> b2
p2
p1
为空,终止。
使用Java即可简单实现:
public static void findMidElOfLinkedList(FindMidElementOfLinkedList findMidElementOfLinkedList) {
Node node = findMidElementOfLinkedList.head;
Node slow = node;
Node fast = node;
while (fast != null && fast.next != null) {
fast = fast.next.next; // increase 2
slow = slow.next; // increate 1
}
System.out.println(slow.data);
/*
* Slow runner goes at a pace of 1 element per move, fast runner goes 2 elements per move.
When the fast runner reaches the end of the linked list, then slow runner is sitting at the middle. Testing this out for one/two middle cases work.
Time O(N), faster than the previous brute force method, Space: O(1).
* */
}
所以,我在这里面临一个疑问。
我正在阅读《破解编码面试》一书。下面的文字写在那里。
假设你有一个链表 a1->a2....->an->b1->b2....bn
,你想将它重新排列成 a1->b1->a2->b2->.....an->bn
。你不知道链表的长度,但你只知道它是一个偶数。
(这里两个链表长度相同)
您可以让一个指针 p1(快速指针)每两个元素移动一次 p2 移动一次。当 p1 到达链表的末尾时,p2 将位于端点。然后,将 p1 移回前面并开始 "weaving" 个元素。在每次迭代中,p2 选择一个元素并将其插入到 p1 之后。
我不明白当p1 到达链表末尾时,p2 会在中点。如果 n=3(长度 = 6),这就是我的想象。下面的每个步骤代表一次迭代。
1. a1 (p1, p2)->a2->a3->b1->b2->b3
2. a1->a2 (p2)->a3 (p1)->b1->b2->b3
3. a1->a2->a3 (p2)->b1->b2 (p1)->b3
4. Index out of bounds error because p2 now points to a node after b3.
我是不是走错地方了?
从第二个位置开始 p2。
a1(p1)-> a2 (p2) -> a3 -> a4 -> b1 -> b2 -> b3 -> b4
a1-> a2 (p1) -> a3 -> a4 (p2)-> b1 -> b2 -> b3 -> b4
a1-> a2 -> a3(p1) -> a4 -> b1 -> b2(p2) -> b3 -> b4
a1-> a2 -> a3 -> a4(p1) -> b1 -> b2 -> b3 -> b4(p2)
让n = 2
。我们从一个列表开始:
a1 -> a2 -> b1 -> b2
令p1
成为一个"fast"指针,最初指向head的后继者。
让 p2
成为一个 "slow" 指针,最初指向头部。
p1
a1 -> a2 -> b1 -> b2
p2
我们将 p1
移动两位,将 p2
移动一位,直到 p1
到达列表的末尾(没有下一个)。
p1
a1 -> a2 -> b1 -> b2
p2
将p1
移回头部。
p1
a1 -> a2 -> b1 -> b2
p2
前进 p2
.
p1
a1 -> a2 -> b1 -> b2
p2
"Weaving" 开始。
将p2
指向的元素移到p1
之后。在插入元素后前进 p1
。
p1
a1 -> b1 -> a2 -> b2
p2
将p2
指向的元素移到p1
之后。在插入元素后前进 p1
。
p1
a1 -> b1 -> a2 -> b2
p2
p1
为空,终止。
使用Java即可简单实现:
public static void findMidElOfLinkedList(FindMidElementOfLinkedList findMidElementOfLinkedList) {
Node node = findMidElementOfLinkedList.head;
Node slow = node;
Node fast = node;
while (fast != null && fast.next != null) {
fast = fast.next.next; // increase 2
slow = slow.next; // increate 1
}
System.out.println(slow.data);
/*
* Slow runner goes at a pace of 1 element per move, fast runner goes 2 elements per move.
When the fast runner reaches the end of the linked list, then slow runner is sitting at the middle. Testing this out for one/two middle cases work.
Time O(N), faster than the previous brute force method, Space: O(1).
* */
}