题解 | #链表内指定区间反转#

链表内指定区间反转

http://www.nowcoder.com/practice/b58434e200a648c589ca2063f1faf58c

代码

import java.util.*;

/*
 * public class ListNode {
 *   int val;
 *   ListNode next = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param head ListNode类 
     * @param m int整型 
     * @param n int整型 
     * @return ListNode类
     */
    public ListNode reverseBetween(ListNode head, int m, int n) {
        if (m == n || m <= 0 || m > n)
            return head;
        ListNode newHead = new ListNode(1);
        newHead.next = head;
        ListNode beforeNode = newHead, endNode = head;
        for (int i = 1; i < m; i++)
            beforeNode = beforeNode.next;
        for (int i = 1; i <= n; i++)
            endNode = endNode.next;
        ListNode currentNode = beforeNode.next;
        ListNode afterNode = currentNode.next;
        beforeNode.next = endNode;
        for (int j = m; j <= n; j++) {
            currentNode.next = beforeNode.next;
            beforeNode.next = currentNode;
            currentNode = afterNode;
            if(currentNode == null){
                break;
            }
            afterNode = afterNode.next;
        }
        return newHead.next;
    }
}

做这道题目之前一定要做第一道链表反转的题,做完了那道题,这道题就容易很多

alt

算法分析

整个过程分为三个阶段

  • 第一阶段 生成新链表,就是只在原链表前新增一个节点。这步非常简单,不用多说。只是提一下这么做的目的,因为后面需要找到调整位置的前一个节点(也就是m值对应链表节点的前一个节点,即下文的beforeNode),如果m=1,没有新增一个节点的话,beforeNode就不好定位了。
  • 第二阶段 调整链表的结构,这一阶段需要找到好几个位置。首先是调整位置的后一个节点(也就是n值对应链表节点的后一个节点,即下文的endNode),从endNode到末尾是不用反转的。同时需要找到链表的调整位置currentNode和afterNode,由于endNode之后的节点都是不需要反转的,这里直接将endNode挂到beforeNode之后。
  • 第三阶段 循环利用头插法往beforeNode之后插入currentNode节点,这里需要注意,整个调整过程中只有currentNode和afterNode节点是变动的,其他节点都只是找到位置,并不发生变化。

最后一个for循环中使用了if判断currentNode是否为空,目的是处理边界条件,即n=size的情况,此时currentNode=null,如果不跳出循环,afterNode=afterNode.next会越界。

算法性能

  • 时间复杂度 整个算法只使用了3个for循环,前两个for循环是为了找节点的位置,后一个for循环是调整,时间复杂度是O(n)。
  • 空间复杂度 整个算法只声明了几个ListNode变量,额外空间复杂度是O(1),比题目中规定的要低。
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务