LeetCode:206. 反转链表(Java)

1,110 阅读2分钟
原文链接: blog.csdn.net

题目:

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

 

解答:

迭代方式:

首先判断链表是不是空的,如果是空的,直接返回null;

对于链表:

放两个指针p1, p2:

不能直接将p2 -> next指向p1,否则链表会断掉。

可以设置一个tmp指针,指向 p2 -> next,保证后续的操作:

然后将p1,p2往前挪动,当然还有tmp,直到p2为空,这时p1指向反转后链表的头结点。

 

最后一次:

刚好结束的时候:

完成了?

不。好像有一点不对劲儿,还多了一个1 -> 2的指针,少了一个null(1 -> null)。正巧head还在,通过head -> next访问多余的指针,指向null(其实一开始就可以这么干的。)

实现代码:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null) { //先考虑链表是否为空
            return null;
        }
        ListNode p1 = head;
        ListNode p2 = head.next;
        p1.next = null;
        while (p2 != null) {
            ListNode temp = p2.next;
            p2.next = p1;
            p1 = p2;
            p2 = temp;            
        }
        return p1;
    }
}

递归方式:

我们可以从另一个角度考虑这件事:

同样地,对于这样一个链表:

我们要反转它,其实可以

然后我们当作这个子链表已经反转完成:

而我们需要的是:

于是我们可以将上上张图的head.next.next = head:像是这样:

然而仅仅这样是不够的,链表到现在有一个明显的环,我们要把这个环去掉:

令head.next = null即可。

完成。

接下来考虑递归结束的条件:非常显然,子链表只有一个节点是递归结束,直接返回该节点。

当然,这个可以和一开始的空值处理(空链表的处理)写到一起。

下面是具体实现:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode subListHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return subListHead;
    }
}