92 Reverse Linked List II

逆转部分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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值