zoukankan      html  css  js  c++  java
  • [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)。

  • 相关阅读:
    关于TCP/IP,这十个问题你都知道,就入门了!
    Hadoop入门
    mysql实现主从复制
    1.5linux基本操作命令----ls
    1.5Linux下的目录介绍
    1.4 yum源的配置
    1.3 防火墙关闭
    1.2网络配置
    Linux学习---CentOS7.6下载与简介(一)
    解决centos7使用yum install -y gcc gcc-c++报错缺少依赖包的问题
  • 原文地址:https://www.cnblogs.com/boris1221/p/9374641.html
Copyright © 2011-2022 走看看