Leetcode:反转链表
方法一:迭代
该方法定义了头节点与尾节点两个变量,通过nextTemp记录指针,指针顺序1->2->3,通过迭代第二步修改引用1<-2<-3。
1 public ListNode reverseList(ListNode head) { 2 //尾节点 3 ListNode prev = null; 4 //头节点 5 ListNode curr = head; 6 while (curr != null) { 7 //记录当前节点的尾节点 8 ListNode nextTemp = curr.next; 9 //修改当前节点尾节点为null,(1->null,2->1->null,3->2->1->null) 10 curr.next = prev; 11 //记录下一节点尾节点 12 prev = curr; 13 //记录下一节点头节点(原节点的尾节点) 14 curr = nextTemp; 15 } 16 return prev; 17 }
复杂度分析
-
时间复杂度:O(n)。 假设 nn 是列表的长度,时间复杂度是 O(n)。
-
空间复杂度:O(1)。
方法二:递归
递归版本稍微复杂一些,其关键在于反向工作。假设列表的其余部分已经被反转,现在我该如何反转它前面的部分?假设列表为:n1 → … → nk-1 → nk → nk+1 → … → nm → Ø
若从节点 nk+1 到 nm 已经被反转,而我们正处于 nk。
n1 → … → nk-1 → nk → nk+1 ← … ← nm
我们希望 nk+1 的下一个节点指向 nk。
所以,
nk.next.next = nk;
要小心的是 n1 的下一个必须指向 Ø 。如果你忽略了这一点,你的链表中可能会产生循环。如果使用大小为 2 的链表测试代码,则可能会捕获此错误。
1 public ListNode reverseList(ListNode head) { 2 //head.next.next = head = nk+1 3 if (head == null || head.next == null) return head; 4 //移动访问指针到最后一个节点 5 ListNode p = reverseList(head.next); 6 //修改最后一个节点得头节点 7 head.next.next = head; 8 head.next = null; 9 return p; 10 }
复杂度分析
-
时间复杂度:O(n) 。 假设 nn 是列表的长度,那么时间复杂度为 O(n)。
-
空间复杂度:O(n)。 由于使用递归,将会使用隐式栈空间。递归深度可能会达到 n 层。