想要精通算法和SQL的成长之路 - 反转链表

想要精通算法和SQL的成长之路 - 反转链表

前言

想要精通算法和SQL的成长之路 - 系列导航

一. 反转链表

原题链接
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
在这里插入图片描述

思路如下: 我们可以通过一次遍历,修改链表节点的指针指向。由于指针修改的时候,指针的引用就变了。我们需要用一个临时变量tmp来保存节点。同时我们需要一个变量pre来标识上一个节点。以及cur代表当前节点。
在这里插入图片描述

那么我们以上图为例,原本的指针是 1 --> 2。我们要做的就是断开这个链接。然后将指针改为 2 --> 1。别看这个操作看似简单,但是真正的实现需要分为如下几个步骤:

  1. 首先,pre的值为nullcur的值就是链表头结点1。我们要提前存储2这个节点的引用(后续指针改变了,就拿不到了),也就是 tmp = cur.next;
  2. 然后,将当前指针的next,改为上一个节点。即反转的实现:cur.next=pre;

这里其实就是相邻节点的一个指针反转了。但是我们既然要整个链表都反转,我们就难以避免递归。因此我们还需要将curpre的指针往后移动。不断地循环上述操作。即:

  1. pre指针后移一位:pre = cur;
  2. cur指针后移一位:cur = tmptmp是最开始存储的cur.next引用)如图:
    在这里插入图片描述

循环终止条件:cur当前指针不为null。最终完整代码如下:

public ListNode reverseList(ListNode head) {
    ListNode cur = head, pre = null, tmp = null;
    while (cur != null) {
        // 1.临时存储下一个节点的引用
        tmp = cur.next;
        // 2.指针反转的核心步骤
        cur.next = pre;
        // 3.pre(上一个指针)往后移
        pre = cur;
        // 4.cur指针同样往后移,进入下一次循环进行指针反转
        cur = tmp;
    }
    return pre;
}

二. 反转链表II

原题链接
在这里插入图片描述

思路如下:

  1. 首先找到反转链表的前置节点pre(不在反转范围内),同时拿到反转链表部分的第一个节点:leftNode
  2. 在找到反转链表部分的最后一个节点rightNode。这样也可以拿到反转链表的后置节点last
  3. 将反转链表的前后指针断开,再对这部分链表做反转,代码同第一题,入参为leftNode
  4. 反转结束,将左右两侧指针接回。pre.next = rightNode。对于leftNode(此时是反转后的最后一个节点)leftNode.next = last

即链表表示:xxx->xxx->pre--> leftNode-->xxx-->rightNode -->last-->xxx[leftNode,rightNode]这部分则是做反转操作。

代码如下:

public void reverseList2(ListNode head) {
    ListNode cur = head, pre = null, tmp;
    while (cur != null) {
        tmp = cur.next;
        cur.next = pre;
        pre = cur;
        cur = tmp;
    }
}

public ListNode reverseBetween(ListNode head, int left, int right) {
    // 记录一个虚拟指针
    ListNode dummy = new ListNode(-1);
    dummy.next = head;
    // 找到切割链表的前置节点pre
    ListNode pre = dummy;
    for (int i = 0; i < left - 1; i++) {
        pre = pre.next;
    }
    // 找到反转链表的最后一个节点last(属于反转链表内的元素)
    ListNode rightNode = pre;
    for (int i = 0; i < right - left + 1; i++) {
        rightNode = rightNode.next;
    }
    // 要想对 [pre.next , last] 区间的链表做反转,先要把两侧的指针给断掉
    ListNode leftNode = pre.next, last = rightNode.next;
    // 切断连接
    pre.next = null;
    rightNode.next = null;
    reverseList2(leftNode);
    // 连接
    pre.next = rightNode;
    leftNode.next = last;
    return dummy.next;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Zong_0915

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

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

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

打赏作者

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

抵扣说明:

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

余额充值