使用下一个方法时,链接列表不会在循环中正确迭代

时间:2017-01-26 06:37:32

标签: java linked-list stack reverse

我正在尝试使用堆栈迭代地反转链表。我已经确定了问题发生的地方,但是对于我的生活,我无法弄清楚当我调用ListNode的下一个方法时代码没有正确迭代的原因。我在下面的代码中标记了错误发生的地方。

这是我运行代码时的结果:

Before: 1->2->3->4->null
After: 4->3->3->4->null

这就是结果:

Before: 1->2->3->4->null
After: 4->3->2->1->null

有人能指出我正确的方向吗?谢谢!

以下是代码:

public class Solution {
    public static void main(String[] args) {
        private static Solution soln = new Solution();
        ListNode head = makeLinkedList(4);

        System.out.print("Before: ");
        printLinkedList(head);
        System.out.println();

        soln.reverseList(head);

        System.out.print(" After: ");
        printLinkedList(head);

        System.exit(0);
    }

    public ListNode reverseList(ListNode head) {
        Stack<ListNode> listContents = new Stack<ListNode>();

        // iterate list and add to stack
        ListNode tmp = head;
        while (tmp != null) {
            listContents.push(tmp);
            tmp = tmp.next;
        }

        // iterate list again and replace each val with stack val
        tmp = head;
        while (tmp != null) {
            tmp.val = listContents.pop().val;
            // this is where the code seems to fail
            tmp = tmp.next; 
        }
        return head;
    }
}

如何定义ListNode:

public class ListNode {
    int val;
    ListNode next = null;

    public ListNode(int item) { 
        val = item; 
    }
}

以下是我创建链接列表的方法:

private static ListNode makeLinkedList(int numNodes) {
    ListNode head = null;
    ListNode tmp = null;
    for (int i = 1; i < numNodes + 1; i++) {
        if (tmp == null) {
            tmp = new ListNode(i);
            head = tmp;
        } else {
            tmp.next = new ListNode(i);
            tmp = tmp.next;
        }
    }
    return head;
}

辅助方法:

private static void printLinkedList(ListNode head) {
    ListNode tmp = head;
    while (tmp != null) {
        System.out.print(tmp.val + "->");
        tmp = tmp.next;
    }
    System.out.print("null");
}

3 个答案:

答案 0 :(得分:3)

为什么不起作用?

问题是您将ListNode存储在Stack而不仅仅是值中。这样,您将覆盖您正在阅读的节点的值:

  • 你从堆栈开始(前排第一):4 - 3 - 2 - 1
  • 你拿前头,弹出堆栈,并写入值
    • 新列表:4
    • 现在堆栈是:3 - 2 - 4 (你在头上覆盖了价值)
  • 下一个元素
    • 新名单:4 - 3
    • 堆栈: 3 - 4(您在第二个列表节点中覆盖了值)
  • 下一个元素
    • 新名单:4 - 3 - 3
    • Stack:4
  • 最后一个元素
    • 新名单:4 - 3 - 3 - 4

如何使其发挥作用?

修复它的几种可能方法:

  • 仅将值存储在堆栈中。
  • 为反向列表创建新的ListNode
  • 重新连接节点,而不是重写其值。请注意,这可以在不使用Stack的情况下完成 - 请参阅@xenteros的回答。

答案 1 :(得分:2)

如果可能,应通过撤消链接来撤消链接列表。我尝试以下方法:

public static ListNode reverseList(ListNode head) {
    // iterate list and add to stack
    ListNode current = head;
    ListNode previous = null;
    ListNode temp = null;
    while (current.next != null) {
        temp = previous;
        previous = current;
        current = current.next;
        previous.next = temp;
    }
    current.next = previous;
    return current;
}

它返回一个新头。用法示例:

public static void main(String[] args) {

    ListNode head = makeLinkedList(4);

    System.out.print("Before: ");
    printLinkedList(head);
    System.out.println();

    head = reverseList(head);

    System.out.print(" After: ");
    printLinkedList(head);

    System.exit(0);
}

>>Before: 1->2->3->4->null
>>After: 4->3->2->1->null
>>Process finished with exit code 0

算法描述如下: 对于列表中的每个节点,不是链接下一个元素,而是链接前一个元素并将最后一个元素作为头部返回。

答案 2 :(得分:1)

这种情况正在发生,因为您在不知道它的情况下改变了LinkedList。换句话说,当你在LinkedList中覆盖任何更多的值时,你之前在堆栈上推送的节点也会被修改。因此,确保不会发生这种情况的一种方法是在堆栈上实例化并推送新节点(副本):

public ListNode reverseList(ListNode head) {
 Stack<ListNode> listContents = new Stack<ListNode>();

 // iterate list and add to stack
 ListNode tmp = head;

 while (tmp != null) {
     ListNode newNode = new ListNode(temp);
     listContents.push(newNode);
     tmp = tmp.next;
 }

 // iterate list again and replace each val with stack val
 tmp = head;
 while (tmp != null) {
     tmp.val = listContents.pop().val;
     tmp = tmp.next; 
 }
 return head;
}

ListNode类进行简单修改以添加复制构造函数:

public class ListNode {
  int val;
  ListNode next = null;

  public ListNode (ListNode that){
     this.val = that.val;
      this.next = null;     //Could be that.next
   }

  public ListNode(int item) { 
      val = item; 
  }
}