92 Reverse Linked List II

来源:互联网 发布:云计算与虚拟化的区别 编辑:程序博客网 时间:2024/06/05 17:03

逆转部分LinkList,和逆转整个LinkList的题目是一样的,沿用之前的思路就可以,新建一个dummyNode,把要逆转的部分通过头插法连接起来。

这道题稍微有点麻烦,就是分步骤:

1,找到逆转部分的之前一个node,作为第一个attach point

2,确定逆转部分的最后一个node,作为第二个attach point

3,完成扭转之后,attach两次既可!

一个技巧,因为m可以等于1,那么逆转部分的前一个node怎么确定呢?那就通过新建一个dummyHead,连在head之前,这样就非常方便了,很多情况下,通过dummyHead可以是问题简化很多。代码如下


/** * Definition for singly-linked list. * public class ListNode { *     int val; *     ListNode next; *     ListNode(int x) { val = x; } * } */public class Solution {    public ListNode reverseBetween(ListNode head, int m, int n) {        if(head==null || head.next==null) return head;                ListNode dummyHead= new ListNode(0);        dummyHead.next=head;        ListNode curr=dummyHead;        int jump=0;        while(jump<m-1){            curr=curr.next;            jump++;        } // after while loop, jump=m-2 and curr points to the node before m-th node                ListNode frontAttach=curr; // set the anchor                // advance 1 node        curr=curr.next;          jump++;                // use the same idea of reverse the whole list        ListNode dummy= new ListNode(0);        ListNode backAttach=curr;        while(jump<=n){            ListNode target=curr;            curr=curr.next;            target.next=dummy.next;            dummy.next=target;            jump++;        }                // do 2 attach, for the reversed segment        frontAttach.next=dummy.next;        backAttach.next=curr;                return dummyHead.next; // Do NOT return head, it is wrong, when m==1    }    }


参考了别人的解法,有一个while循环就完成逆转的,代码是比较简洁,但是while内部的多次node 移动不是非常intuitive,需要画图才看得清楚,可能在熟悉之后还是可以使用的,如果头脑里没有这个画面,还是不要轻易使用, 容易出错。代码如下

public ListNode reverseBetween(ListNode head, int m, int n) {    if(head == null) return null;    ListNode dummy = new ListNode(0); // create a dummy node to mark the head of this list    dummy.next = head;    ListNode pre = dummy; // make a pointer pre as a marker for the node before reversing    for(int i = 0; i<m-1; i++) pre = pre.next;        ListNode start = pre.next; // a pointer to the beginning of a sub-list that will be reversed    ListNode then = start.next; // a pointer to a node that will be reversed        for(int i=0; i<n-m; i++)    {        start.next = then.next;        then.next = pre.next;        pre.next = then;  // 以上三句就是每次把then node移动到pre后面,这样就完成了逆转,pre和start之间的node顺序已经稳定,所以不需要做改变        then = start.next; // 始终保持then在start后面    }        return dummy.next;    }

结合我代码的思路,这上面的代码其实还比较好理解,

第一个for loop,通过移动m-1次,把光标指针移到m-1个node处,然后初始化start,和始终在start后面的end

第二个for loop,本质就是挪动n-m次node,所以有i=0; i<n-m,每次挪动需要换图来理解,至少画2个循环才看得清楚,第一次的pre.next 和第二次的pre.next的区别就让你看得清楚了。有了理解和画面感,还是比较容易记忆的。





0 0
原创粉丝点击