数组Arr(大小为n)可以表示双向链表。 [假设细胞有结构{int val,next,prev; }]
我有两个存储在数组中的列表A和B. A有m个节点,B有n个m节点。
这些节点被分散,我想重新排列它们,使得A的所有节点都来自Arr [0] .Arr [m-1]并且其余部分由B的节点填充,在O(m)时间内。 / p>
我遇到的解决方案是:
然而,在这种情况下,迭代总数为O(n + m)。因此应该有一个更好的答案。
P.S: 这个问题出现在Introduction to Algorithms, 2nd edition中。 问题10.3-5
答案 0 :(得分:2)
如何迭代列表 A 并将每个元素放在Arr[0] ... Arr[m-1]
中,显然用之前的任何内容交换位置并更新prev / next链接。会有很多交换但是它会是 O(m),因为一旦你完成迭代 A ( m 迭代),所有其元素的位置(按顺序顺序)位于Arr
的第一个 m 个插槽中,因此 B 必须完全位于{的其余部分{1}}。
添加一些伪代码
Arr
答案 1 :(得分:0)
我认为“jw013”是对的,但这个想法需要一些改进:
通过交换你正在改变Arr数组中元素的地址。 所以你需要小心!
e.g。我们可以说Arr喜欢:
指数:0 1 2 3 4
| 2 | empty | 3 | empty | 1 | (assume the link list is like 1 -> 2 -> 3)
因此Arr[4].next
为0而Arr[0].next
为2。
但是当你交换Arr[4]
和Arr[0]
时,Arr[0].next
为0。
这不是我们想要发生的事情所以我们应该考虑在交换时调整指针。
所以它的代码就像:
public static void compactify(int List_head , int Free , node [] array){
int List_lenght ;
List_lenght = find_listlenght(List_head , array);
if(List_lenght != 0){ // if the list is not empty
int a = List_head;
for (int i = 0; i < List_lenght ; i++) {
swap( array , a , i );
a = array[i].next;
print_mem(array);
}
}
}
现在调用swap:
private static void swap(node[] array, int a, int i) {
// adjust the next and prev of both array[a] and array[i]
int next_a = array[a].next;
int next_i = array[i].next;
int prev_a = array[a].prev;
int prev_i = array[i].prev;
// if array[a] has a next adjust the array[next_a].prev to i
if(next_a != -1)
array[next_a].prev = i;
// if array[i] has a next adjust the array[next_i].prev to a
if(next_i != -1)
array[next_i].prev = a;
// like before adjust the pointers of array[prev_a] and array[prev_i]
if(prev_a != -1)
array[prev_a].next = i;
if(prev_i != -1)
array[prev_i].next = a;
node temp = array[a];
array[a] = array[i];
array[i] = temp;
}