反转链表解释+力扣刷题

反转链表解析

学习过链表的朋友们都知道,链表的节点是由指针和数值组成的,每个指针都指向下一个链表,这就是链表的逻辑结构,而反转链表实际上就是将指针反转过来,指向前一个元素,且头节点指向null

在解决此类问题的时候,我们可以使用cur来代表当前元素, pre来代表当前元素的前一个元素,nxt来代表当前元素的后一个元素。

而过程则是从头节点开始,头节点指向null,头节点的下一个节点指向头节点……,如此往复,就是下面的过程:

在这里插入图片描述

反转完成之后,pre指向这一段链表的末尾,cur指向这一段的下一个节点。

理清楚之后,我们就可以看下面的题啦~

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

img

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

img

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

题目分析

这是一道简单题,实际上就是简单地描述一个反转链表的过程,代码如下:

代码

/**
 * Definition for singly-linked list.
 * 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; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode pre = null;
        ListNode cur = head;
        
        while(cur != null){
            ListNode nxt = cur.next;
            cur.next = pre;
            // 下面这俩顺序不能反!
            pre = cur;
            cur = nxt;
        }
        return pre;
    }
}

92.反转链表II

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

示例 1:

img

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例 2:

输入:head = [5], left = 1, right = 1
输出:[5]

提示:

  • 链表中节点数目为 n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n

题目分析

本题其实和上题类似,多了一个范围设定 [ l e f t , r i g h t ] [left, right] [left,right],我们假设这一段链表的前面一个链表为p0,由于我们在分析反转链表时得到了一个结论:**反转完成之后,pre指向这一段链表的末尾,cur指向这一段的下一个节点。**那么我们此时就可以假设pre r i g h t right right对应的节点,cur r i g h t right right后的一个节点。

如下图,反转完成之后,p0.next指向cur,而p0指向pre

在这里插入图片描述

此题分析到这还没完哦,当left = 1时,没有p0节点了怎么办?很简单,我们只需要在一整段链表前加一个”哨兵节点“就可以啦~

在这里插入图片描述

代码

/**
 * Definition for singly-linked list.
 * 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; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        ListNode dummy = new ListNode(0, head);
        ListNode p0 = dummy;
        // 使p0到达反转这一段的上一个节点
        for(int i = 0; i < left - 1; i ++) p0 = p0.next;

        ListNode pre = null;
        ListNode cur = p0.next;
        for(int i = 0; i < right - left + 1; i ++){
            ListNode nxt = cur.next;
            cur.next = pre;
            pre = cur;
            cur = nxt;
        }
        p0.next.next = cur;
        p0.next = pre;
        return dummy.next;
    }
}

25. K个一组翻转链表

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

示例 1:

img

输入:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]

示例 2:

img

输入:head = [1,2,3,4,5], k = 3
输出:[3,2,1,4,5]

提示:

  • 链表中的节点数目为 n
  • 1 <= k <= n <= 5000
  • 0 <= Node.val <= 1000

题目分析

这道题和上道题其实就是一样的,只是多了一个 k k k来控制翻转,具体我们看图:

在这里插入图片描述

代码

/**
 * Definition for singly-linked list.
 * 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; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        ListNode dummy = new ListNode(0, head);
        ListNode p0 = dummy;
        // 获取链表长度
        ListNode cur = head;
        int n = 0;
        while(cur != null){
            n ++;
            cur = cur.next;
        }
        cur = head;
        ListNode pre = null;
        while(n >= k){
            n -= k;
            for(int i = 0; i < k; i ++){
                ListNode nxt = cur.next;
                cur.next = pre;
                pre = cur;
                cur = nxt;
            }
            ListNode nxt = p0.next;
            p0.next.next = cur;
            p0.next = pre;
            p0 = nxt;
        }
        return dummy.next;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值