龙空技术网

链表内指定区间反转

乐天派爱思考的考拉 47

前言:

此刻看官们对“反转链表牛客网”大约比较着重,看官们都想要剖析一些“反转链表牛客网”的相关文章。那么小编也在网上收集了一些有关“反转链表牛客网””的相关知识,希望兄弟们能喜欢,咱们快快来了解一下吧!

描述

将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n)O(n),空间复杂度 O(1)O(1)。 例如: 给出的链表为 1→2→3→4→5→NULL, m=2,n=4m=2,n=4, 返回 1→4→3→2→5→NULL.

问题分析

练习了简单的链表反转,我们知道可以通过双指针的方式来完成链表的反转,那么我们应该如何把指定区间的链表反转和这个联系起来呢,我们可以找到prevMNode(mNode的前一个节点),mNode,nNode,nextNNode,然后将mNode,nNode这段链表反转,最后将这三段链表连接起来,组成一个新的链表,这样,指定区间的链表反转就完成了,下面我们使用图例来看一下链表的反转过程。

通过图例,我们可以看出链表反转的过程,同时,我们也发现了一个问题,当我们是从链表的头部开始反转的时候,这个时候,我们还需要判断mNode是否有prevMNode,这会让程序变得复杂,那么,我们有什么好的办法呢?答案就是定义一个虚拟的头结点。

算法实现

下面,我们来看一下代码实现

/* * 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) {        // write code here        // 判断不需要反转的条件        if(head == null || m >= n) {            return head;        }        // 定义虚拟的头结点        ListNode dummy = new ListNode(-1);        dummy.next = head;        head = dummy;                ListNode prevM = head;        // 寻找prevM        for(int i = 0; i < m - 1; i++) {            prevM = prevM.next;        }        // prevM的下一个节点即为mNode        ListNode mNode = prevM.next;        ListNode nNode = mNode;        ListNode postNode = nNode.next;        // 使用双指针法反转链表        for(int i = m; i < n; i++) {            ListNode next = postNode.next;            postNode.next = nNode;            nNode = postNode;            postNode = next;        }        // 重组链表        mNode.next = postNode;        prevM.next = nNode;        // 虚拟头结点的下一个节点即为新的头结点        return dummy.next;    }}

算法需要练习才能掌握精髓,附上算法练习地址,有需要的小伙伴可以上去练习一下

链表内指定区间反转_牛客题霸_牛客网

注:牛客网上的算法题按照专题分类,更适合突击训练使用

标签: #反转链表牛客网