[leetcode] Reverse Linked List

Posted Lin.B

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[leetcode] Reverse Linked List相关的知识,希望对你有一定的参考价值。

1、Reverse Linked ListⅠ

Reverse a singly linked list.

Example:

Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL

Follow up:

A linked list can be reversed either iteratively or recursively. Could you implement both?

分析:链表的翻转,时链表类题目里最基础的了,和判断链表是否有环一样。是链表里面必须掌握的两个方法。
用栈来做当然也是可以的,不过空间复杂度高了。所以用时间复杂度为O(n)空间复杂度为O(1)的方法。思路也比较清晰,用三个指针,从前向后遍历链表。
 
根据上面的思路,得到代码如下:
 1 class Solution {
 2     public ListNode reverseList(ListNode head) {
 3         ListNode p,q,ptr;
 4         p = head;
 5         q = null;
 6         while( p != null ){
 7             ptr = p.next;
 8             p.next = q;
 9             q=p;
10             p = ptr;
11         }
12         return q;
13     }
14 }

     运行时间0ms。


2、Reverse Linked List II

Reverse a linked list from position m to n. Do it in one-pass.

Note: 1 ≤ m ≤ n ≤ length of list.

Example:

Input: 1->2->3->4->5->NULL, m = 2, n = 4
Output: 1->4->3->2->5->NULL 
分析:第二个问题也是翻转链表,但是要求m—n位置翻转,其余位置不变。其实思路还是上面的思路,只是可以增加一个累加表示访问到的位置。
这个问题可以分为三段来考虑,比如1->2->3->4->5->null,翻转2到4位置,就分成三段,1->null,2->3->4,5->null,这里标红要注意不能空指。
步骤其实很简单,我们主要的工作还是翻转中间那段,变成:2<-3<-4。然后,1指到4,2指到5。这样就完成了链表的翻转。
由此可见我们需要四个指针,第一个指针first0指向第一段最后一个节点,first1指向要翻转的那段第一个节点,q指向要翻转的那段最后一个节点,ptr指向最后一段第一个节点。
这里一定要注意将三段拼接起来的时候要注意分类讨论:第一种情况是从开头到最后全部翻转,第二种情况是从开头开始翻转到中间某个位置,第三种情况是从中间某个位置反转到最后,第四种情况是从中间某个位置到中间某个位置翻转。因为不同的情况,指针指向的位置是不同的。
还是看代码比较清晰:
 1 class Solution {
 2     public ListNode reverseBetween(ListNode head, int m, int n) {
 3         if ( m >= n ) return head;
 4         ListNode p,q,ptr = null;
 5         ListNode first0 = head,first1;
 6         p = head;
 7         q = null;
 8         int count = 1;
 9         while ( count < m ){
10             first0 = p;
11             p = p.next;
12             count++;
13         }
14         //此时,p指针指向第一个要变动的位置,first0指针指向最后一个不变的元素。
15         first1 = p;
16         while ( count <= n  ){
17             ptr = p.next;
18             p.next = q;
19             q = p;
20             p = ptr;
21             count ++;
22         }
23         //此时完成m—n位置的翻转,然后拼接上三段
24         //注意这里分类讨论。第一种情况是全部翻转,第二种情况是从开头开始翻转到中间某个位置,第三种情况是从中间某个位置反转到最后,第四种情况是从中间某个位置到中间某个位置翻转。
25        if ( ptr == null && first0 == first1) {
26             return q;
27         }
28         if ( ptr == null ){
29             first0.next = q;
30             return head;
31         }
32         if ( first0 == first1 ){
33             first1.next = ptr;
34             return q;
35         }
36         first1.next = ptr;
37         first0.next = q;
38         return head;
39     }
40 }

      运行时间2ms,基本上应该是最快的解法了。时间复杂度O(n),空间复杂度O(1)。

以上是关于[leetcode] Reverse Linked List的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 92. Reverse Linked List II

Leetcode Reverse Linked List

#Leetcode# 92. Reverse Linked List II

Leetcode 206 Reverse Linked List 链表

[Leetcode]Reverse Linked List II

LeetCode 206 Reverse Linked List