LeetCode 206.反转链表

112 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目:给定单链表的头节点,要求反转此单链表,并且返回反转后的单链表的头节点。要求分别使用迭代法和递归法实现。

解题思路

迭代法很容易理解,首先创建一个头节点,该头节点中存放无效数据,之后遍历单链表,使用单链表的头插法即可得到最终结果。迭代法所需要注意的就是每次要从单链表中断开遍历到的节点,并且要保存该节点的next节点,完成头插法后更新当前节点即可。可得代码如下:

public ListNode reverseList(ListNode head) {
        ListNode headPoint = new ListNode(-1);
        while(head!=null){
            ListNode curNext = head.next;
            head.next = headPoint.next;
            headPoint.next = head;
            head = curNext;
        }
  }

上述代码的时间复杂度为O(n)O(n),空间复杂度为O(1)O(1)

如何使用递归的方式得到最终的结果应该是本题考查的关键,首先判断递归的结束条件应该是什么?

递归的过程无非就是不断调用reverseList,并且将head.next传入,那最终必然会遍历到空指针,我们以链表[1, 2, 3, 4, 5]作为示例,我们希望最终得到的节点是5,那么递归终止条件是不是就可以直接设置为if(head.next==null) return head,这种方式是不对的,当链表不为空的时候,这种方式固然正确,但如果链表中不存在元素的话,则会出现空指针异常,因此递归终止条件应该设置为:if(head==null||head.next==null) return head。而当我们获得5的时候,此时的5后面连接的应该是4,仔细想此时的head实际上也是4,因此只需设置head.next.next=head就可以将4连接上,但我们还需要将4和之前的链表断开,因此执行head.next=null。根据此思路可得代码如下:

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

可惜该算法的时间复杂度和空间复杂度都是O(n)O(n)