LeetCode 92.反转链表Ⅱ

1.思路:找到要反转区间的前一个位置preLeftNode和它的下一个节点LeftNode,然后对待反转区间的元素进行反转,然后重新连接链表。preLeftNode去连反转链表的新头节点,反转区间的最后一个节点LeftNode去连反转区间后的第一个节点。

2.复杂度分析:

(1)时间复杂度:O(right)。

(2)空间复杂度:O(1)。

附代码:

java 复制代码
class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        if(head == null){
            return null;
        }
        // 创建一个哨兵节点,它的next指向head(当left等于1的时候,即left指向head的时候,head也要做反转)
        ListNode sentinel = new ListNode();
        sentinel.next = head;
        // 找到反转区间前面的节点preLeftNode
        // preLeftNode就是left前面的一个位置
        ListNode preLeftNode = sentinel;
        for(int i = 1;i < left;i++){
            preLeftNode = preLeftNode.next;
        }
        // leftNode表示反转区间的第一个节点,待会反转后会变为尾部
        ListNode leftNode = preLeftNode.next;

        // pre节点表示当前节点的前一个节点,初始为null,区间节点全部反转后会成为反转后的头部
        ListNode pre = null;
        // cur初始指向反转区间的第一个节点leftNode
        ListNode cur = leftNode;

        // 依次遍历要反转的节点,进行反转
        for(int i = 0;i < right - left + 1;i++){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }

        // 重新连接链表
        // 反转区间前面的节点preLeftNode连接到反转后的头部pre
        preLeftNode.next = pre;
        // 反转后的尾部连接到反转区间后的第一个节点cur(此前cur已走到temp,即反转区间末尾节点的后一个节点cur.next的位置)
        leftNode.next = cur;
        // 返回完整链表的头节点
        return sentinel.next;
    }
}

ACM模式:

java 复制代码
import java.util.Scanner;

// 将 ListNode 定义为独立的类
class ListNode {
    int val;
    ListNode next;
    ListNode() {};
    ListNode(int val) {
        this.val = val;
        this.next = null;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取链表长度
        int n = scanner.nextInt();

        // 读取链表元素
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) {
            nums[i] = scanner.nextInt();
        }

        // 读取 left 和 right
        int left = scanner.nextInt();
        int right = scanner.nextInt();

        // 创建链表
        ListNode head = null;
        if (n > 0) {
            head = new ListNode(nums[0]);
            ListNode current = head;
            for (int i = 1; i < n; i++) {
                current.next = new ListNode(nums[i]);
                current = current.next;
            }
        }

        // 调用反转区间链表方法
        Solution solution = new Solution();
        ListNode result = solution.reverseBetween(head, left, right);

        // 输出反转后的链表
        if (result == null) {
            System.out.println("");
        } else {
            ListNode current = result;
            while (current != null) {
                System.out.print(current.val);
                if (current.next != null) {
                    System.out.print(" ");
                }
                current = current.next;
            }
            System.out.println();
        }

        scanner.close();
    }
}

// 反转区间链表方法放在 Solution 类中
class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        if(head == null){
            return null;
        }
        // 创建一个哨兵节点,它的next指向head(当left等于1的时候,即left指向head的时候,head也要做反转)
        ListNode sentinel = new ListNode();
        sentinel.next = head;
        // 找到反转区间前面的节点preLeftNode
        // preLeftNode就是left前面的一个位置
        ListNode preLeftNode = sentinel;
        for (int i = 1; i < left; i++) {
            preLeftNode = preLeftNode.next;
        }
        // leftNode表示反转区间的第一个节点,待会反转后会变为尾部
        ListNode leftNode = preLeftNode.next;

        // pre节点表示当前节点的前一个节点,初始为null,区间节点全部反转后会成为反转后的头部
        ListNode pre = null;
        // cur初始指向反转区间的第一个节点leftNode
        ListNode cur = leftNode;

        // 依次遍历要反转的节点,进行反转
        for (int i = 0; i < right - left + 1; i++) {
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }

        // 重新连接链表
        // 反转区间前面的节点preLeftNode连接到反转后的头部pre
        preLeftNode.next = pre;
        // 反转后的尾部连接到反转区间后的第一个节点cur(此前cur已走到temp,即反转区间末尾节点的后一个节点cur.next的位置)
        leftNode.next = cur;
        // 返回完整链表的头节点
        return sentinel.next;
    }
}
相关推荐
wanzehongsheng13 分钟前
基于天文算法的双轴太阳能追踪系统:从原理到工程实现
算法
basketball61615 分钟前
Kadane算法 C++实现
java·c++·算法
handler0116 分钟前
【C++】二叉搜索树详解及其模拟实现(代码)
开发语言·c++·算法·c··二叉搜索树·搜索树
luj_176818 分钟前
残熵算法的稳健防灾逻辑
c语言·开发语言·c++·经验分享·算法
玖釉-19 分钟前
二叉树基础详解:TreeNode、buildTree、deleteTree 与 printTree 的实现原理(C++)
c++·windows·算法
Severus_black19 分钟前
【初阶数据结构与算法】八大排序之非比较排序(计数排序),一次性讲清!
数据结构·算法·排序算法
罗西的思考42 分钟前
【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (4)--- 系统架构
人工智能·算法·机器学习
QiLinkOS44 分钟前
从技术到资产的跃迁:企业专利布局的深层逻辑
c语言·数据结构·c++·单片机·嵌入式硬件·算法·开源
aini_lovee1 小时前
FMCW雷达测速测距系统(锯齿波 + CFAR检测)
算法
qq_297574671 小时前
设计模式系列文章(基础篇第 11 篇):模板方法模式——定义算法骨架,实现代码复用与流程统一
算法·设计模式·模板方法模式