以下是我在网站上发现的使用LinkedList的问题:
编写一个方法移位,重新排列整数列表的元素,方法是移动到列表末尾所有奇数位置的值,否则保留列表顺序。例如,假设变量列表存储以下值:
[0, 1, 2, 3, 4, 5, 6, 7]
list.shift()的调用;应该将列表重新排列为:
[0, 2, 4, 6, 1, 3, 5, 7]
在此示例中,原始列表中的值等于它们的位置,并且存在偶数个元素,但情况不一定如此。例如,如果列表存储了以下内容:
[4, 17, 29, 3, 8, 2, 28, 5, 7]
然后调用list.shift();列表将存储:
[4, 29, 8, 28, 7, 17, 3, 2, 5]
请注意,值本身是奇数还是偶数无关紧要。重要的是该值是否出现在奇数索引(索引1,3,5等)中。另请注意,否则将保留列表的原始顺序。您可能无法构造任何新节点,并且您可能不使用任何辅助数据结构来解决此问题(没有数组,ArrayList,堆栈,队列,字符串等)。您也可以不更改节点的任何数据字段;你必须通过重新安排列表的链接来解决这个问题。
我首先难以理解这一点。在第一个例子中,
[0, 1, 2, 3, 4, 5, 6, 7]
move(index 1) will give [0,2,3,4,5,6,7,1]
move(index 3) will give [0,2,3,5,6,7,1,4]
我已经打破了预期的转变。我不明白这个问题。 关于这个问题的提示以及如何处理这个问题会非常有帮助。
更新:通过理解以下答案实现了这一点:
public void shift() {
if (front==null)
return;
ListNode curr = front;
ListNode temp = curr.next;
while (curr.next!=null && curr.next.next != null) {
curr.next = curr.next.next;
curr = curr.next;
temp.next = curr.next;
}
curr.next = temp;
temp.next = null;
}
input: [3, 3, 3, 3, 4]
expected output: front -> [3] -> [3] -> [4] -> [3] -> [3]
my output: front -> [3] -> [3] -> [4] -> [3]
input: [0, 1, 2, 3, 4, 5, 6, 7]
expected output: front -> [0] -> [2] -> [4] -> [6] -> [1] -> [3] -> [5] -> [7]
expected output: front -> [0] -> [2] -> [4] -> [6] -> [1]
从我的输出中可以看出,我没有正确地重新链接临时节点。即临时节点没有得到更新。但我不知道为什么?
答案 0 :(得分:1)
您正在考虑在每次移动后基本上将索引重新计算到列表中。
他们真正考虑从列表中移动其他项目,就像它最初存在一样。
预期的难点在于跟踪何时停止重新排列元素。您希望在最初位于列表中的最后一个节点之后停止,但如果您以最明显的方式执行此操作,那么当您到达那里时,它将不再是列表中的最后一个节点。
微妙提示:即使假设单链表无法直接找到最后一个节点,您仍然可以只通过一次遍历列表来完成工作。
这样做有点棘手。在遍历第一个列表时,不是将每个节点添加到原始列表的末尾,而是在遍历原始列表时将这些节点放在单独的临时列表中。当您到达原始列表的末尾时,然后通过将原始列表末尾的空指针更改为指向临时列表的开头(并且因为您',将整个临时列表拼接到原始列表的末尾)到达最后,您将临时列表的最后一个节点中的“下一个”指针设置为NULL)。
这对于数组来说通常是不切实际的,因为你暂时需要为数组中一半元素提供额外的存储空间。但是,对于链接列表,您只需要两个额外的指针:一个用于临时列表的开头,另一个用于临时列表中的最后一个节点。
答案 1 :(得分:0)
您在实施中犯了一个小错误,您不希望每次都temp
更新temp.next=curr.next;
。您希望将变量保留在列表的开头,然后将变量作为列表的最后一个元素(并且您将下一个临时节点附加到此元素,并且永远不会触及第一个元素)。然后将第一个元素追加到原始列表的末尾。
当你构建一个列表时,你总是保留2个两个指针:一个在列表的开头(所以你可以完全使用它),一个在列表的末尾添加元素。这就是为什么你在O(1)
中最后添加元素而你要在n
中的O(n)
位置添加元素(你需要迭代n个第一个元素)。
Jerry Coffin在他的最后一段中暗示了这一点。
也许您应该看看如何构建列表? http://en.wikipedia.org/wiki/Linked_list(我认为您正在实施简单的链接列表。)
答案 2 :(得分:0)
试试这个: 代码不言自明:如果你不理解,发表评论,我会澄清
public void switchPairs() {
if (front != null && front.next != null) {
ListNode current = front.next;
front.next = current.next;
current.next = front;
front = current;
current = current.next;
while (current.next != null && current.next.next != null) {
ListNode temp = current.next.next;
current.next.next = temp.next;
temp.next = current.next;
current.next = temp;
current = temp.next;
}
}
}
答案 3 :(得分:0)
下面的代码片段会生成您要求的确切输出。 阅读内联评论。 干杯!
/**
* A method that strips the even and odd elements in a Linkedlist
*/
public static void zipper(LinkedList list) {
LinkedList head = list;
LinkedList oddHead = head;
LinkedList evenHead = head.getNext();
LinkedList oddMove = oddHead;
LinkedList evenMove = evenHead;
while (head != null && evenMove != null && oddMove != null) {
oddMove.next = head.next.next; // set the link to appropriate
// position for odd list
oddMove = oddMove.next; // move the pointer to new head of odd list
head = head.next; // move original head
if (head != null) {
evenMove.next = head.next; // set the link to appropriate
// position for even list
evenMove = evenMove.next; // move the pointer to new head of
// even list
}
}
LinkedList temp2 = oddHead;
while (temp2.next != null) {
//System.out.println(temp2.elem);
temp2 = temp2.next;
}
temp2.next = evenHead;
System.out.println("----------------elems------------------");
while (oddHead != null) {
System.out.println(oddHead.elem);
oddHead = oddHead.next;
}
System.out.println("------------------------------------------------");}
答案 4 :(得分:0)
这是Java实现
public static LinearNode<Integer> seperateEvenAndOddIndexNodes(LinearNode<Integer> head) {
LinearNode<Integer> prevNode =null, currentNode = head, tail = head, nextNode;
int length = length(head),index = 0;
if (length < 3) {
return head;
}
while (tail != null && tail.next() != null) {
tail = tail.next();
}
while (currentNode != null && index < length) {
nextNode = currentNode.next();
if (index % 2 == 1) {
LinearNode<Integer> temp = currentNode;
tail.next(temp);
tail = temp;
prevNode.next(nextNode);
currentNode = prevNode;
temp.next(null);
}
prevNode = currentNode;
currentNode = nextNode;
index++;
}
return head;
}
这是单元测试用例
@Test
public void seperateEvenAndOddIndexesTest() {
LinearNode<Integer> head = buildLinkedList(1,2,3,4,5,6);
head = LinkedListUtil.seperateEvenAndOddIndexNodes(head);
assertLinkedList(head, 1,3,5,2,4,6);
head = buildLinkedList(1);
head = LinkedListUtil.seperateEvenAndOddIndexNodes(head);
assertLinkedList(head, 1);
head = buildLinkedList(1, 2);
head = LinkedListUtil.seperateEvenAndOddIndexNodes(head);
assertLinkedList(head, 1, 2);
head = buildLinkedList(1, 2, 3);
head = LinkedListUtil.seperateEvenAndOddIndexNodes(head);
assertLinkedList(head, 1, 3, 2);
}
答案 5 :(得分:0)
这是O(n)的工作代码: 想法是你传递对空列表q的引用以及原始列表。切片p->接下来,将其追加到列表q,其尾部始终指向原始列表p的开头。 请注意,此解决方案仅适用于在所有节点之前放置偶数节点的情况。您可以轻松更改逻辑,反之亦然。
int main() {
NODEPTR list = create_list(10);
NODEPTR q = NULL;
odd_even_part(list, &q);
printf("\n Here is list after partitionining and rearranging :\n");
recursive_print(q);
return 0;
}
/* Use recursion to build rearranged list q */
NODEPTR odd_even_part(NODEPTR p, NODEPTR* q) {
NODEPTR temp = NULL;
if(p == NULL || p->next == NULL) {
return p;
}
else {
temp = p->next;
p->next = temp->next;
if((*q) == NULL) {
(*q) = temp;
temp->next = p;
}else {
temp->next = (*q)->next;
(*q)->next = temp;
}
odd_even_part(p->next,&temp);
}
}
答案 6 :(得分:0)
可以通过将大列表重组为两个较小的列表来解决此问题,一个较小的列表具有偶数索引元素,而另一个具有奇数索引元素。创建这两个子列表后,将它们合并在一起,并将front
设置为合并列表的开头。
为了最终合并两个列表,您将需要四个变量。指向每个子列表前面的两个变量分别称为evenFront
和oddFront
,以及两个变量来循环访问子列表,分别称为even
和odd
。
将even
初始化为front
(由于列表为零索引,因此列表中的第一个偶数索引元素位于索引为零,也称为front
)并初始化{ {1}}到odd
(出于相同的原因,列表中的第一个奇数索引元素位于索引1,front.next
之后的下一个元素)。
这是我的代码。
front