LeetCode-206 reverse-linked-list 反转链表

版权声明:转载请注明原址,有错误欢迎指出 https://blog.csdn.net/iwts_24/article/details/83315465

题目链接

reverse-linked-list

题意

中文题,反转链表,给出链表头,要求输出一个链表头,oj会遍历以判定是否反转。

题解

        简单的方法是迭代,然后反向输出。或者说利用额外空间储存遍历链表的数据,然后在构造一个链表头,反向输出额外空间储存数据来创建一个新链表。但是链表的遍历本来就是利用指针指向一层一层向下遍历,并且是反向输出,很自然能想到利用递归的方法。在回溯的时候输出就可以了。但是这不是ACM,可以看到方法的返回值是一个ListNode对象,也就是要求构造出一个链表,并返回链表头。如果在回溯的时候构造很麻烦,因为还得回溯下一个引用指向的对象。所以我们可以在原来的链表上进行修改。

        这里先上一下代码,下面是图解:

public ListNode reverseList(ListNode head) {
    if(head == null || head.next == null){
        return head;
    }
    ListNode next = head.next;
    head.next = null;
    ListNode ret = reverseList(next);
    next.next = head;
    return ret;
}

那么首先是递归过程:

可以看到,在递归的时候,ret在等待回溯结果,等到第三层递归,返回最后一个节点,之前先声明每个节点的next是null。因为反转以后最后一个节点的next必须是null。

        接下来是回溯的过程:

可以看到,回溯过程实际上每次向上传递的永远都是最后一个节点,那么最后返回的结果就是最后一个节点了,而这也是反转链表的head。那么除了这个过程,可以看到主要做了3件事:

1.当前节点.next = null

2.下层节点.next = 当前节点

第一步的作用是防止最后一个节点的next不是null,而第二步的作用实际上是翻转链表。因为递归的时候已经遍历过的节点就可以删除联系了,因为没有用了。最终层层向上回溯的只是最后一个节点。但是在递归的时候从第一个节点开始已经完成了翻转,第一个节点的next也变成了null。这样,就能在不额外大量开辟空间(实际上是多了next这个对象)的情况下进行反转操作。

Java 代码

/**
 * 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 next = head.next;
        head.next = null;
        ListNode ret = reverseList(next);
        next.next = head;
        return ret;
    }
}

猜你喜欢

转载自blog.csdn.net/iwts_24/article/details/83315465