链表反转问题二

算法通关村第二关 ——  白银挑战之链表反转拓展问题

本文以介绍与链表反转有关的一些拓展问题,如:

        指定区间反转(头插法、穿针引线法)

        两两交换链表中的节点

指定区间反转

        如图:指定2 - 4节点反转,1、5节点不变

        

         

        方法一:头插法

        先遍历到开始反转的节点,用临时节点保存一下断开的前一个节点cur,断开的后一个节点一个temp(该节点为反转后继续往后连接的节点),然后使用头插法使left到right反转,随后把temp接回虚拟节点处;

    /**
     * 头插法
     */
    public static void headInsert(Node<Integer> head, int left, int right) {
        if (head == null) {
            return;
        }
        Node<Integer> dummyNode = new Node<>(-1);
        Node<Integer> cur = head;
        for (int i = 1; i < left - 1; i++) {
            cur = cur.getNext();
        }
        Node<Integer> pre = cur.getNext();
        Node<Integer> temp = pre;
        for (int i = 0; i <= right - left ; i++) {
            Node<Integer> next = pre.getNext();
            pre.setNextNode(dummyNode.getNext());
            dummyNode.setNextNode(pre);
            pre = next;
        }
        //尾节点接上
        temp.setNextNode(pre);
        //断开的节点接上
        cur.setNextNode(dummyNode.getNext());
    }

                

        方法二:穿针引线法

        先记录断开前的pre,第二段断开前的rightNode,以及第二段断开后的下一个节点suc,记录反转的第一个节点为leftNode = pre.next,使用穿针引线法反转,随之pre -> rightNode -> pre.next -> suc,注意,此处第三部没有用leftNode而是用pre.next,是因为在遍历的最后面,leftNode = suc了,而pre的next并没有变,所以可以先连接起后面的,再把前面的连起来

        

    /**
     * 穿针引线法
     */
    public static void middle(Node<Integer> head, int left, int right) {
        Node<Integer> node = head;
        for (int i = 1; i < left - 1; i++) {
            node = node.getNext();
        }
        Node<Integer> pre = node;
        Node<Integer> leftNode = pre.getNext();
        for (int i = 0; i <= right - left; i++) {
            node = node.getNext();
        }
        Node<Integer> rightNode = node;
        Node<Integer> suc = rightNode.getNext();

        Node<Integer> sub = null;
        while (leftNode != suc){
            Node<Integer> next = leftNode.getNext();
            leftNode.setNextNode(sub);
            sub = leftNode;
            leftNode = next;
        }
        pre.getNext().setNextNode(suc);
        pre.setNextNode(rightNode);
    }

两两交换链表中的节点

        实现效果:        

       

        利用上虚拟节点,设(1)虚拟节点 temp、(2)当前节点cur、(3)下一个节点next、(4)下一个开始的节点nextStart,取这4各临时变量进行一下交换与赋值

        ①:cur、next(next指向cur,temp指向next)交换

        ②:cur指向nextStart

        ③:temp移到cur处,作为下一个循环的起点

        

     /**
     * 两两交换链表中的节点
     * */
    public static Node<Integer> coupleChange(Node<Integer> head){
        if (head == null){
            return null;
        }
        Node<Integer> dummyNode = new Node<>(-1);
        dummyNode.setNextNode(head);
        Node<Integer> temp = dummyNode;
        while (temp.getNext() != null && temp.getNext().getNext() != null ){
            Node<Integer> cur = temp.getNext();
            Node<Integer> next = cur.getNext();
            Node<Integer> nextStart = next.getNext();
            temp.setNextNode(next);
            next.setNextNode(cur);
            cur.setNextNode(nextStart);
            temp = cur;
        }
        return dummyNode.getNext();
    }

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值