你如何从单个链表(在一个遍历中)中获得尾部的第n个节点?

时间:2013-09-23 19:39:02

标签: algorithm linked-list singly-linked-list

所以我从考试中得到了这个问题。

如何在单链表中从尾部获取第n个节点?

每个节点都有一个值和一个下一个(它是指向下一个值的指针)。我们得到了这个:

getNodeFromTail(Node head, int x) {

}

所以我这样做的方法是通过遍历一次来查找列表的长度。然后再去获取(length-x)节点。总共有2次遍历。

getNodeFromTail(Node head, int x) {
    int length = 0;
    Node headdupe = head;
    while (headdupe.next != NULL) {
         headdupe = headdupe.next;
         length++;
    }
    int a = length--;
    for (int y = 0; y < a; y++) {
         head = head.next;
    }
    return head;
}

这是对的,但也有一个额外的问题,即询问我们是否可以做同样的事情,但只能遍历一次。我在考试期间无法想到它,但在我想到一种方式后,我对此并不太确定。

我可以创建一个长度为x的ArrayList。然后每次我运行while循环时,我都会在数组的顶部添加一个元素,向下级联并启动数组的最后一个元素。然后当头部命中null时,返回数组[x-1]的节点。

这是对的吗?有更好的解决方案吗?

6 个答案:

答案 0 :(得分:6)

  1. 指向第一个节点
  2. 的2个指针
  3. x
  4. 推进一个指针
  5. 并排推进两个指针,直到列表中的另一个指针结束。
  6. 您的指针后退指向x最后一个元素。

答案 1 :(得分:2)

我会做以下事情:

保留大小为x的循环缓冲区,并在遍历列表时向其添加节点。到达列表末尾时,尾部的第x个等于循环缓冲区中的下一个条目。

在伪代码中:

Node getNodeFromTail(Node head, int x) {
  // Circular buffer with current index of of iteration.
  int[] buffer = new int[x];
  int i = 0;

  do {
    // Place the current head in its position in the buffer and increment
    // the head and the index, continuing if necessary.
    buffer[i++ % x] = head;
    head = head.next;
  } while (head.next != NULL);

  // If we haven't reached x nodes, return NULL, otherwise the next item in the
  // circular buffer holds the item from x heads ago.
  return (i < x) ? NULL : buffer[++i % x];
}

此解决方案在内存中需要额外的x,这是交换内存运行时的经典示例。

注意:如果输入列表小于x,该怎么做是未定义的。

答案 2 :(得分:2)

保持2个指针, 从头开始前进第一个指向第N个节点的指针 现在指向第二指针 继续前进两个指针,直到第一个到达结束 第二个指针现在指向最后一个

案例列表中的额外关注少于N个元素

答案 3 :(得分:1)

您可以在不经过两次或递归的情况下完成此操作。 请参阅以下内容:

int getNodeFromTail(Node head, int position)
{
    if (head == NULL)
      return 0;

      // 2 pointers needed
      Node first = head;
      Node sec = head;

      for(int i = 0; i < position; i++)
        sec = sec.next;

      while (sec.next != NULL)
      {
        sec = sec.next;
        first = first.next;
      }

      return first;
}

答案 4 :(得分:1)

你不需要2个低效的循环,只需使用2个指针和一个计数器:

<div ng-class="{myClass:true, 'class-cool':openDialog}"></div>

答案 5 :(得分:0)

这是最简单的解决方案

static int getNodeNoStack(ListNode head, int k) {
    ListNode result = head;
    int count = 0;
    while(head.next != null) {
        if(count < k) {
            count++;
        } else {
            result = result.next;
        }
        head = head.next;
    }
    return result.val;
}

您只需要将指针“结果”保持在从头部遍历整个列表到末尾的距离k处。一旦头位于末尾,则结果指针将位于从尾到第k的位置