LeetCode Java刷题笔记—92. 反转链表 II

92. 反转链表 II

反转从位置 left 到 right 的链表,返回反转后的链表头节点。需要使用一趟扫描完成反转。

这道题相比于206题,难度加大,206题可以看做是此题的特例,即left=1,right=length。

因此,对于这道题,我们要先找到需要进行反转的位置,然后进行部分反转。

/**
 * 92. 反转链表 II
 * 反转从位置 left 到 right 的链表,返回反转后的链表头节点。需要使用一趟扫描完成反转。
 * https://leetcode-cn.com/problems/reverse-linked-list-ii/
 * 中等
 */
public class LeetCode92{

   /**
    * 指针
    *
    * @param head
    * @param left
    * @param right
    * @return
    */
   public ListNode reverseBetween( ListNode head, int left, int right ){
      //由于head节点可能被交换位置,因此需要哨兵节点
      ListNode dummy = new ListNode( 0, head );
      ListNode pre = dummy;
      //pre指向需要反转的链表部分的首节点的前驱
      for( int i = 1; i < left; ++i ){
         pre = pre.next;
      }
      // head指向当前需要反转的链表节点
      head = pre.next;
      //开始反转,每次需要改变三个节点的引用关系,同时已经反转了的节点的关系不变
      for( int i = left; i < right; ++i ){
         //获取当前需要反转的节点的后继
         ListNode next = head.next;
         //当前节点的后继指向后继节点的后继
         head.next = next.next;
         //后继节点的后继指向前驱节点的后继
         next.next = pre.next;
         //前驱节点的后继指向当前节点的后继,完成反转
         pre.next = next;
      }
      return dummy.next;
   }

   public class ListNode{

      int val;
      ListNode next;

      ListNode(){

      }

      ListNode( int val ){

         this.val = val;
      }

      ListNode( int val, ListNode next ){

         this.val = val;
         this.next = next;
      }
   }
}

我们采用上面的算法,假设链表数据为{1、2、3、4、5},left=2,right=4,下面是算法流程图。

当我们找到需要进行反转的节点之后,在进行循环之前,数据结构以及变量的关系如下:

在这里插入图片描述

进入循环体,开始第一次反转。首先计算出next = head.next。

在这里插入图片描述

然后我们需要将head和head.next进行反转,但是这两个节点之前和之后的引用必须保持不变。

我们首先设head.next = next.next,这样head节点就是next节点之后的链表关联起来了。

在这里插入图片描述

然后设next.next = pre.next,这样head和next节点的引用就反转了。

在这里插入图片描述

最后我们还需要设pre.next = next,next节点作为pre节点的新后继,这样反转的节点和之前的链表节点也关联起来了。

在这里插入图片描述

这样一轮循环就结束了,看起来很乱,我们调整一下顺序。

在这里插入图片描述

是不是一下就明白了,我们发现,2和3节点已经交换了,同时它们之前和之后的节点关系也没有改变。

下面开始第二轮循环。首先计算出next = head.next。

在这里插入图片描述

进行head.next = next.next,next.next = pre.next,pre.next = next操作。

在这里插入图片描述

这样第二轮循环就结束了,看起来很乱,我们调整一下顺序。

在这里插入图片描述

到此,进行了两轮循环,此时不满足循环条件,退出循环。我们发现此时已经完成了反转,注意我们需要返回dummy.next。

我们还可以发现,在循环过程中,pre和head始终指向同一个节点,这是不变的,改变的只是这些节点的next的指向,这就是这个循环的精妙之处。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘Java

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值