Reverse Singly LinkedList的方法探讨

来源:互联网 发布:淘宝网如何收藏宝贝 编辑:程序博客网 时间:2024/06/06 09:16

今天在做LeetCode的一道Reverse Singly LinkedList题时,从discuss中汲取了不少经验,写文一篇做为总结和思考。

1.三个pointer迭代的常规方法



如图1所示,给出一个链表,现在我们要做的是把它翻转过来使得最终变为5->4->3->2->1的形式。最自然的想法是我们将每一个正在访问的结点(记为current)的next指针指到它的前一个结点(记为parent)。但是这样会有一个小问题,当current的next被重新赋值之后,current原本的下一个结点会丢失,所以我们还需要一个指针then来记录原链表中current的下一个结点。假设我们刚开始进行reverse的操作,第一个操作的结点是2,所有的记号如图2所示。






现在将current指向parent,结果如图3。从图中可以看到,有了then的存在,我们就可以找到下一个要访问的结点,继续往前遍历链表。
为了叙述简单,这里不考虑边界条件,给出该方法的主要循环体:

current.next = parent;parent = current;current = then;then = then.next;

遇到边界条件,如head为空,链表长度不足3个等情况,处理起来也很容易。这里有一个链表中常用的技巧,就是使用一个不关心它存的值是多少的dummy node,把它放置在头结点的前面,这样可以省去关于头结点的边界条件判断。

2.头插法

此方法和建立链表时使用的头插法是一个意思,就是在一个链表的头部不断插入新的结点。在reverse完成后,原链表的头结点将成为新链表的尾部,因此我们把它记为tail。假设我们添加了一个dummy node在结点1的前面,那么头插法的运行过程如下:
访问继tail之后的第一个结点current,并把current拿出来,插入到链表的最前面(dummy node的后面),这样tail和current的位置就发生了交换。过程如图4所示。



然后,将current的值更新为此时tail所指向的下一个结点,再次重复该操作,直到末尾即可。这里给出完整的实现代码。

public ListNode reverseList(ListNode head) {    if(head == null || head.next == null) return head;        ListNode dummy = new ListNode(0);    dummy.next = head;    ListNode tail = dummy.next;    ListNode cur = tail.next;    while(cur != null) {        tail.next = cur.next;        cur.next = dummy.next;        dummy.next = cur;        cur = tail.next;    }    return dummy.next;}

相比于第一个方法,个人觉得这种方法比较容易操作,需要考虑的东西比较少,当然第一个方法是最容易想到的。