算法通关村第二关——指定区间反转问题解析

引言:以下内容均只是个人看法,并无严格经过核对,如有异议,欢迎交流,发现错误,欢迎您的及时指正,感谢!本文所示代码均为java代码

本文中使用的结点定义语句如下

public class ListNode {
       public int val;
       public ListNode next;
       ListNode(int x) {
           val = x;
           //这个一般作用不大,写了会更加规范
           next = null;
       }
}

单链表的遍历一般从第一个结点依次遍历整个链表,所以第一个结点十分重要,在本文中头节点指的是第一个存放数据的结点,与其他相关文章中关于它的定义可能不同,无需深究,理解相关操作的逻辑原理即可,本质上无较大差别。

leetcode92题

给出单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表。

示例一:
输入:[1,2,3,4,5] left=2 right=4
输出:[1,4,3,2,5]

1.头插法

也就是在需要反转的区间用头插法来实现反转

代码如下

    /**
     *
     * @param head 需要进行指定区间反转的链表的头结点
     * @param left 指定区间的开始位置
     * @param right 指定区间的结束位置
     * @return
     */
    //头插法
    public static ListNode reverseBetween1(ListNode head, int left, int right) {
        ListNode dum=new ListNode(0);
        //虚拟头结点
        dum.next=head;
        ListNode pre=dum,cur=null,next=null;
        for(int i=0;i<left;i++){
            pre=pre.next;
        }
        cur=pre.next;
        for(int i=0;i<right-left+1;i++){
            //一次循环做一次指定区间的头插
            next=cur.next;
            cur.next=next.next;
            next.next=pre.next;
            pre.next=next;
        }
        return dum.next;
    }

2.穿针引线法

穿针引线法其实是找到需要反转的区间,然后将该区间进行反转操作,最后利用提起记录的几个指针,把反转后的区间重新连接到原链表中。

代码如下

    /**
     *
     * @param head 需要进行指定区间反转的链表的头结点
     * @param left 指定区间的开始位置
     * @param right 指定区间的结束位置
     * @return
     */
    //串针引线法
    public static ListNode reverseBetween2(ListNode head, int left, int right) {
        ListNode dum=new ListNode(0);
        dum.next=head;
        ListNode pre=dum,leftNode=null,rightNode=null,succ=null;
        //pre作为一个临时指针用来指向left前一位的结点,pre.next就是leftNode指针要指向的结点
        //之后让rightNode向后遍历,直到指向right位置的结点,rightNode.next就是succ要指向的结点
        for(int i=0;i<left-1;i++){
        pre=pre.next;
        }
        rightNode=pre;
        for(int i=0;i<right-left-1;i++){
            rightNode=rightNode.next;
        }
        leftNode=pre.next;
        succ=rightNode.next;
        //这里修改rightNode为null,是为了防止在反转过程中超过right
        rightNode.next=null;
        reverseList2(leftNode);
        pre.next=rightNode;
        leftNode.next=succ;
        return head;
    }
    public static ListNode reverseList2(ListNode head){
        //cur指向下一个待反转的节点 ,pre作为反转了的部分的当前头结点
       ListNode cur=head,pre=null;
        while(cur!=null){
            ListNode next=cur.next;
            cur.next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值