Day25:反转链表

113 阅读2分钟

描述

给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。

题源:反转链表_牛客题霸_牛客网 (nowcoder.com)

数据范围: 0\leq n\leq10000≤n≤1000

要求:空间复杂度 O(1)O(1) ,时间复杂度 O(n)O(n) 。

如当输入链表{1,2,3}时,

经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。

以上转换过程如下图所示:

示例1

输入:

{1,2,3}

返回值:

{3,2,1}

示例2

输入:

{}

返回值:

{}

说明:

空链表则输出空 

思路:

从上述方法一,我们可以看到每当我们反转链表的一个节点以后,要遍历进入下一个节点进入反转,相当于对后续的子链表进行反转,这可以看成是一个子问题,因此我们也可以使用递归,其三段式模版为:

  • 终止条件:  当到达链表尾,要么当前指针是空,要么下一个指针是空,就返回。
  • 返回值:  每一级返回反转后的子问题的头节点。
  • 本级任务:  先进入后一个节点作为子问题。等到子问题都反转完成,再将本级节点与后一个的指针反转。

具体做法:

  • step 1:对于每个节点我们递归向下遍历到最后的尾节点。
  • step 2:然后往上依次逆转两个节点。
  • step 3:将逆转后的本层节点,即反转后这后半段子链表的尾,指向null,返回最底层上来的头部节点。 一:用栈的方式
class Solution {
    public ListNode ReverseList(ListNode head) {
        Stack<ListNode> stack = new Stack<ListNode>();
        ListNode temp = head;
        while (temp != null){
            stack.push(temp);
            temp = temp.next;
        }
        ListNode head1 = stack.pop();
        ListNode temp1 = head1;
        while (!stack.empty()){
           temp1.next = stack.pop();
           temp1 = temp1.next;
        }
        temp1.next = null;
        return head1;
    }
}

二: 递归

public ListNode ReverseList(ListNode head) {
    if (head == null || head.next == null) return head;
   ListNode head1 = ReverseList(head.next);
   head.next.next = head;
   head.next = null;
   return head1;
}

时间复杂度:O(N),其中 N 是链表的长度。需要遍历链表一次。

空间复杂度:O(1),常数空间复杂度