学习反转链接列表

时间:2016-06-26 02:34:56

标签: java

我有以下代码来反转链接列表:

public class ProgrammingInterviews {

    public static void main(String[] args) {
        List list = new List();
        list.add(new Node(1));
        list.add(new Node(2));
        list.add(new Node(3));
        list.add(new Node(4));
        list.reverse();
        System.out.println(list);
    }

}

class List {
    Node head;
    public List() {
        head = new Node(0);
    }

    public void add(Node node) {
        if (head.next == null) {
            head.next = node;
        } else {
            Node temp = head.next;
            while (temp.next != null) {
                temp = temp.next;
            }
            temp.next = node;
        }
    }

    public void reverse() {
        this.head = reverse(this.head);
    }

    private Node reverse(Node n) {
        if (n == null || n.next == null) {
            return n;
        }
        Node remaining = reverse(n.next);
        n.next.next = n;
        n.next = null;
        return remaining;

    }

    public String toString() {
        Node temp = head;
        String result = "HEAD";
        while (temp.next != null) {
            result = result + "->" + temp.next.data;
            temp = temp.next;
        }
        return result;
    }
}

class Node {
    int data;
    Node next;

    public Node(int data) {
        this.data = data;
    }
}

我试图让它打印HEAD->4->3->2->1但没有用。但是,它正在打印HEAD->3->2->1。我有什么遗失的。

另外,如果您有如何解决这些类型问题的提示,那将对我有所帮助。我已经做了一段时间的编程了。它非常适合解决问题。我很容易想出天真的解决方案。但是,在数据结构和算法的领域,我们通过不同的想法/方式思考提出解决方案,我总是觉得很短。

例如,在这个问题中,我从未想过使用递归有一个解决方案。我正在使用其他地方查找的解决方案。如果我得到一些技巧可以帮助我解决这些类型的问题,那将会非常有用。

1 个答案:

答案 0 :(得分:0)

问题在于如何概念化链表的头部。构建列表时,请指定:

public List() {
    head = new Node(0);
}

该列表理论上是空的,但我们已经有了一个元素!您的数据结构并不能准确地表示数据,但在大多数情况下,您可以通过查看head.next来忽略它。例如:

public String toString() {
    Node temp = head;
    String result = "HEAD";
    while (temp.next != null) {
        result = result + "->" + temp.next.data;
        temp = temp.next;
    }
    return result;
}

你正在通过查看temp.next来查看列表。由于我们从头开始,我们从不看它的值,我们打印的第一个值是head.next(如果它不是null)。

现在,看一下反向方法:

public void reverse() {
    this.head = reverse(this.head);
}

听起来有点奇怪吗?我们有假的价值,我们故意忽略它,但现在我们已经覆盖了它。我们用它覆盖了什么?

好吧,如果reverse()正常工作,新头将是旧的最后一个元素。在你的情况下,那将是...... 4元素!但是我们忽略了toString()中的头部,所以4将永远不会被打印出来。

我运行你提供的代码,它实际上打印HEAD->3->2->1->0,这不应该是一个惊喜,因为列表被反转,而ghost 0元素现在已被推到最后。

我的建议是尝试保持结构简单:当列表为空时,头部应该为空。而不是while(temp.next != null),也许你可以做while(temp != null),因为我们不再有一个基节点(如果头为空,head.next是非法的),最后temp.next element的next应始终为null(这不适用于add(),因为我们需要对最后一个元素的引用)。