【算法】 链表反转以及升级难度-递归和迭代解法(纪录篇)

在这里插入图片描述

链表反转-问题描述
  1. 现存一个单项链表,next指向下一个节点(如图),node1->node2->node3->node4->node5
  2. 问:如何实现把链表反转成:node5->node4->3->node2->node1
    在这里插入图片描述
初步思想
  • 我的第一思想是:我遍历到最后然后再来倒序的进行链表反转;感觉对于反转的话,第一时间我肯定需要找到最后一个节点,然后把他变为头节点,然后再找到次级节点然后再反转指针,不过这个怎么实现呢,一头晕。bigo,突然想了一下,我递归到最深层,然后把指针反转。
  • 初步去实现了一下代码,没有深层次的解。因为这种只会为了实现时间复杂度和空间复杂度都会成阶层的增加。
public ListNode test(ListNode head){
        ListNode last = head.next;
        if(head.next==null){
            return head;
        }else{
            test(head.next);
        }
        // 找到last最后的一个元素,然后指向head
        ListNode curr = last;
        while (curr!=null){
        }
    }
解法
迭代法
  1. 我可以新建立一个节点prevNode,然后遍历整个原链表,当遍历到第一个元素node1的时候,把prevNode的next指向node;
    在这里插入图片描述

  2. 当遍历第二个元素node2的时候,用一个临时的next元素存储prevNode.next元素,即node1;接下来prevNode.next指向node2,后续node2.next指向临时的next元素,即node1;在这里插入图片描述

  3. 当遍历第三个元素node3的时候,用一个临时的next元素存储prevNode.next元素,即node2;接下来prevNode.next指向node3,后续node3.next指向临时的next元素,即node2;在这里插入图片描述

  4. 当遍历第四个元素node4的时候,用一个临时的next元素存储prevNode.next元素,即node3;接下来prevNode.next指向node4,后续node4.next指向临时的next元素,即node3;
    在这里插入图片描述

  5. 当遍历第五个元素node5的时候,用一个临时的next元素存储prevNode.next元素,即node4;接下来prevNode.next指向node5,后续node5.next指向临时的next元素,即node4;
    在这里插入图片描述

是不是结果就已经把链表反转了node5->node4->3->node2->node1。

public ListNode flipNode(ListNode node){
		//prevNode节点
        ListNode prev = null;
        // 下一个节点
        ListNode next ;
        // 循环节点
        ListNode curr = node;
        // 遍历最后节点结束
        while (curr!=null){
        	// 记录next节点
            next = curr.next;
            // 指向前一个节点
            curr.next=prev;
            // 记录前一个节点
            prev = curr;
            // 当前执行的节点
            curr = next;
        }
        return prev;
    }
递归法

思路:

  1. 当前节点node的下一个节点的next指针指向当前节点即:node.next.next=node;

  2. 当前节点node的next指向null;(这里存在一个问题就是node2的指针指向了node1,那么浅蓝色的这个指针也没有了,那么就找不到node3节点了)
    在这里插入图片描述

  3. 那么通过迭代的方式直接倒序的方式来执行,先迭代到最后一个元素开始执行次方式那么:
    在这里插入图片描述

  4. 后续就都是一样的操作了。话不多说直接上代码

    public ListNode flipNode1(ListNode node){
    	// 临界点,边界值返回条件
        if(node==null||node.next==null){
            return node;
        }
        // 递归找最后一个元素
        ListNode last = flipNode1(node.next);
        // node的下一个节点的next指向node
        node.next.next=node;
        // node的next指向null
        node.next=null;
        return last;
    }
升级版本来了

既然是链表反转,那么可以指定一个区间进行局部链表的反转?
链表:node1->node2->node3->node4->node5
指定区间[2,4],那么结果是node1->node4->node3->node2->node5;

这个时候大家能理解透彻前面的解法,其实这个升级版本也不是太难,也有一些自己的想要解的想法了,其实大部分还是差不多的。(其实我也是这么想的,然而还是花了一定的时间写出来)

还是使用的递归法,具体细节就不细讲了,简单来说就是记录区间前一个节点和区间后一个节点,然后区间中实现链表反转
 private ListNode prev = null;
    private ListNode next = null;
    public ListNode flip(ListNode node,int n,int m,int num){
        num++;
        if(num==n-1){
            prev = node;
        }else if(num>=n&& num<=m){
            if(node==null||node.next==null||(num==m)){
                next=node.next;
                prev.next=node;
                return node;
            }
            ListNode last = flip(node.next,n,m,num);
            node.next.next=node;
            if(num==n){
                node.next=next;
            }else{
                node.next=null;
            }
            return last;
        }
        return flip(node.next,n,m,num);
    }
总结

链表反转虽然是一个很简单的算法,但是真正实际写的时候还是有很多需要注意的,比如使用迭代解法的时候,是需要记录prev节点和next节点,还要考虑while的结束条件;递归解法其实也是需要考虑递归临界条件,还有就是空间的思维,哪个节点的next指向哪里。所以我不想做一个只会伪代码的人,想法出来一定要去写,不然以后你的想法都会消失,要相信实操过后,身体是会有记忆的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值