每日算法-250328

news2025/4/1 5:45:49

记录今天学习和解决的LeetCode算法题。


92. 反转链表 II

题目

Problem 92 Description

思路

本题要求反转链表中从 leftright 位置的节点。我们可以采用 头插法 的思路来反转指定区间的链表。

具体来说,我们首先定位到 left 位置节点的前一个节点 prev。然后,从 left 位置开始,依次将 left + 1right 位置的节点移动到 prev 节点的后面,也就是反转区间的“头部”。

解题过程

  1. 虚拟头节点 (Dummy Node): 为了方便处理 left = 1 的情况(即反转从头节点开始),我们创建一个虚拟头节点 dummy,并让 dummy.next 指向原始链表的头节点 head。最终返回结果时返回 dummy.next

  2. 定位 prev 节点: 我们需要找到反转区间的前一个节点,记为 prev。通过一个循环,将 prev 指针从 dummy 开始向后移动 left - 1 步,使其指向第 left - 1 个节点。

  3. 定位 cur 节点: cur 指针初始化为 prev.next,即反转区间的第一个节点(第 left 个节点)。

  4. 执行反转 (头插法): 进行 right - left 次操作。在每次操作中:

    • 记录 cur 的下一个节点,记为 curNext。这curNext 就是本次需要移动到反转区间头部的节点。
    • curnext 指针指向 curNext 的下一个节点,即将 curNext 从链表中暂时断开。 (cur.next = curNext.next;)
    • curNext 插入到 prev 节点的后面:让 curNextnext 指针指向当前反转区间的第一个节点 (prev.next)。 (curNext.next = prev.next;)
    • 更新 prevnext 指针,使其指向新插入的 curNext,这样 curNext 就成为了新的反转区间的第一个节点。 (prev.next = curNext;)
    • 注意:在这个过程中,cur 指针始终指向原来的第 left 个节点,它在反转后会成为反转区间的最后一个节点。 prev 指针始终不变,指向反转区间的前一个节点。
  5. 返回结果: 所有操作完成后,dummy.next 指向的就是新链表的头节点,返回 dummy.next

复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是链表的长度。需要遍历链表找到 prev 节点,然后进行 right - left 次节点移动操作。
  • 空间复杂度: O ( 1 ) O(1) O(1),只使用了常数级别的额外空间(几个指针变量)。

Code

/**
 * 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) {
        // 创建虚拟头节点,简化边界处理(如 left=1)
        ListNode dummy = new ListNode(0);
        dummy.next = head;

        // 1. 移动 prev 指针到第 left-1 个节点
        ListNode prev = dummy;
        for (int i = 1; i < left; i++) {
            prev = prev.next;
        }

        // 2. cur 指针指向第 left 个节点,即反转区间的起始节点
        ListNode cur = prev.next;

        // 3. 执行头插法反转 [left, right] 区间
        // 进行 right - left 次操作
        for (int i = left; i < right; i++) {
            // a. 记录待移动的节点 curNext
            ListNode curNext = cur.next;
            // b. cur 指向 curNext 的下一个节点,将 curNext 从链表中断开
            cur.next = curNext.next;
            // c. 将 curNext 插入到 prev 之后(成为反转区间的新头部)
            curNext.next = prev.next;
            // d. 更新 prev 的 next 指针
            prev.next = curNext;
        }

        // 4. 返回新链表的头节点
        return dummy.next;
    }
}

1004. 最大连续1的个数 III

题目

Problem 1004 Description

思路

本题可以使用 滑动窗口 的方法解决。

核心思想是维护一个窗口 [left, right],使得这个窗口内包含的 0 的数量不超过 k。在窗口滑动过程中,不断更新窗口的最大长度。

解题过程

  1. 初始化: 设置窗口左右边界 left = 0, right = 0,当前窗口内 0 的计数 count = 0,以及最大窗口长度 maxLen = 0
  2. 扩展窗口: 移动 right 指针向右扩展窗口。
    • 如果 nums[right]0,则 count 加 1。
  3. 收缩窗口: 当窗口内 0 的数量 count 超过 k 时,需要收缩窗口。
    • 移动 left 指针向右收缩窗口。
    • 如果移出窗口的元素 nums[left]0,则 count 减 1。
    • 持续收缩直到 count <= k
  4. 更新结果: 在每次窗口调整(扩展或收缩)后,当前窗口 [left, right] 都是一个合法的窗口(0 的数量不超过 k)。计算当前窗口长度 right - left + 1,并更新 maxLen = Math.max(maxLen, right - left + 1)
  5. 遍历结束: 当 right 指针到达数组末尾时,maxLen 即为所求的最大连续1的个数(允许翻转 k 个0)。
  6. 返回结果: 返回 maxLen

复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums 的长度。每个元素最多被 leftright 指针访问一次。
  • 空间复杂度: O ( 1 ) O(1) O(1),只使用了常数级别的额外空间。

Code

class Solution {
    public int longestOnes(int[] nums, int k) {
        int maxLen = 0; // 记录最大窗口长度
        int zeroCount = 0; // 记录当前窗口内 0 的个数
        int left = 0; // 窗口左边界

        // right 指针负责扩展窗口
        for (int right = 0; right < nums.length; right++) {
            // 如果新进入窗口的元素是 0,增加 zeroCount
            if (nums[right] == 0) {
                zeroCount++;
            }

            // 当窗口内 0 的数量超过 k 时,收缩窗口
            while (zeroCount > k) {
                // 如果移出窗口的元素是 0,减少 zeroCount
                if (nums[left] == 0) {
                    zeroCount--;
                }
                // 移动左边界
                left++;
            }

            // 此时窗口 [left, right] 是合法的,更新最大长度
            maxLen = Math.max(maxLen, right - left + 1);
        }

        return maxLen;
    }
}

1658. 将 x 减到 0 的最小操作数

题目

Problem 1658 Description

思路

逆向思维 + 滑动窗口

题目要求从数组两端移除元素,使得移除元素的和等于 x,并求最小的操作次数(即移除元素的最少数量)。

我们可以反向思考:从两端移除元素,等价于在数组中间保留一段 连续 的子数组,使得这段子数组的和等于 totalSum - x

那么问题就转化为:找到数组 nums 中和为 target = totalSum - x最长 连续子数组的长度 maxLen。如果找到了这样的子数组,则最小操作数就是 n - maxLen(其中 n 是数组总长度)。如果找不到,则说明无法通过移除操作使和为 x,返回 -1

我们可以使用滑动窗口来寻找和为 target 的最长连续子数组。

解题过程

  1. 计算总和: 计算数组 nums 的总和 totalSum
  2. 计算目标和: 计算目标子数组的和 target = totalSum - x
  3. 处理边界情况:
    • 如果 target < 0,说明 xtotalSum 还大,不可能通过移除元素得到 x,直接返回 -1
    • 如果 target == 0,说明需要移除所有元素,其和才等于 x (x == totalSum)。此时最长子数组长度为 0,操作数为 n - 0 = n
  4. 滑动窗口: 使用滑动窗口寻找和为 target 的最长连续子数组。
    • 初始化 left = 0, currentSum = 0, maxLen = -1 (-1 表示尚未找到满足条件的子数组)。
    • right 指针遍历数组,扩展窗口,将 nums[right] 加入 currentSum
    • currentSum > target 时,收缩窗口:从 currentSum 中减去 nums[left],并向右移动 left 指针,直到 currentSum <= target
    • 如果 currentSum == target,说明找到了一个和为 target 的子数组 [left, right]。更新 maxLen = Math.max(maxLen, right - left + 1)
  5. 返回结果:
    • 如果 maxLen 仍然是 -1,说明没有找到和为 target 的子数组,返回 -1
    • 否则,返回 n - maxLen

复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums 的长度。计算总和需要 O ( n ) O(n) O(n),滑动窗口也需要 O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1),只使用了常数级别的额外空间。

Code

class Solution {
    public int minOperations(int[] nums, int x) {
        int n = nums.length;
        long totalSum = 0; // 使用 long 防止整数溢出
        for (int num : nums) {
            totalSum += num;
        }

        // 计算目标子数组的和
        long target = totalSum - x;

        // 边界情况:x 比总和还大,无解
        if (target < 0) {
            return -1;
        }
        // 边界情况:x 等于总和,需要移除所有元素
        if (target == 0) {
            return n;
        }

        int maxLen = -1; // 记录和为 target 的最长子数组长度,初始化为 -1 表示未找到
        long currentSum = 0;
        int left = 0;

        // 滑动窗口寻找和为 target 的最长子数组
        for (int right = 0; right < n; right++) {
            currentSum += nums[right];

            // 当窗口和大于 target 时,收缩窗口
            while (currentSum > target && left <= right) {
                currentSum -= nums[left];
                left++;
            }

            // 如果窗口和等于 target,更新 maxLen
            if (currentSum == target) {
                maxLen = Math.max(maxLen, right - left + 1);
            }
        }

        // 如果 maxLen 仍为 -1,说明找不到和为 target 的子数组,返回 -1
        // 否则,返回 n - maxLen
        return maxLen == -1 ? -1 : n - maxLen;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2324071.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从 Word 到 HTML:使用 Aspose.Words 轻松实现 Word 文档的高保真转换

从 Word 到 HTML&#xff1a;使用 Aspose.Words 轻松实现 Word 文档的高保真转换 前言一、环境准备二、核心代码实现1. 将 Word 转换为 HTML 文件流2. 优化超链接样式 三、测试效果四、总结 前言 在日常开发中&#xff0c;我们经常需要将 Word 文档转换为 HTML&#xff0c;用于…

RSA 简介及 C# 和 js 实现【加密知多少系列_4】

〇、简介 谈及 RSA 加密算法&#xff0c;我们就需要先了解下这两个专业名词&#xff0c;对称加密和非对称加密。 对称加密&#xff1a;在同一密钥的加持下&#xff0c;发送方将未加密的原文&#xff0c;通过算法加密成密文&#xff1b;相对的接收方通过算法将密文解密出来原文…

机器学习——LightGBM

LightGBM(light gradient boosting machine&#xff0c;轻量梯度提升机)是对XGBoost进行改进的模型版本&#xff0c;其三者之间的演变关系为&#xff1a;GBDT-》XGBoost-》LightGBM&#xff0c;依次对性能进行优化&#xff0c;尽管XGBoost已经很高效了&#xff0c;但是仍然有缺…

故障识别 | 基于改进螂优化算法(MSADBO)优化变分模态提取(VME)结合稀疏最大谐波噪声比解卷积(SMHD)进行故障诊断识别,matlab代码

基于改进螂优化算法&#xff08;MSADBO&#xff09;优化变分模态提取&#xff08;VME&#xff09;结合稀疏最大谐波噪声比解卷积&#xff08;SMHD&#xff09;进行故障诊断识别 一、引言 1.1 机械故障诊断的背景和意义 在工业生产的宏大画卷中&#xff0c;机械设备的稳定运行…

[已解决]服务器CPU突然飙高98%----Java程序OOM问题 (2024.9.5)

目录 问题描述问题排查问题解决参考资料 问题描述 业主单位服务器自8月29日晚上21:00起CPU突然飙高至98%&#xff0c;内存爆满&#xff0c;一直到9月5日&#xff1a; 问题排查 ①执行 top 命令查看Java进程PID top②执行top -Hp PID 命令查看具体的线程情况 top -Hp 3058输入上…

Ai工作流工具有那些如Dify、coze扣子等以及他们是否开源

Dify &#xff08;https://difycloud.com/&#xff09; 核心定位&#xff1a;专业级 LLM 应用开发平台&#xff0c;支持复杂 AI 工作流构建与企业级管理。典型场景&#xff1a;企业智能客服、数据分析系统、复杂自动化流程构建等。适合需要深度定制、企业级管理和复杂 AI 逻辑…

Yolo_v8的安装测试

前言 如何安装Python版本的Yolo&#xff0c;有一段时间不用了&#xff0c;Yolo的版本也在不断地发展&#xff0c;所以重新安装了运行了一下&#xff0c;记录了下来&#xff0c;供参考。 一、搭建环境 1.1、创建Pycharm工程 首先创建好一个空白的工程&#xff0c;如下图&…

软件兼容性测试的矩阵爆炸问题有哪些解决方案

解决软件兼容性测试中的矩阵爆炸问题主要有优先级划分、组合测试方法、自动化测试技术等方案。其中&#xff0c;组合测试方法尤其有效。组合测试通过科学的组合算法&#xff0c;能够显著降低测试用例的数量&#xff0c;同时保持较高的测试覆盖率&#xff0c;例如正交实验设计&a…

嵌入式学习(32)-TTS语音模块SYN6288

一、概述 SYN6288 中文语音合成芯片是北京宇音天下科技有限公司于 2010年初推出的一款性/价比更高,效果更自然的一款中高端语音合成芯片。SYN6288 通过异步串口(UART)通讯方式&#xff0c;接收待合成的文本数据&#xff0c;实现文本到语音(或 TTS 语音)的转换。宇音天下于 2002…

从零到一:打造顶尖生成式AI应用的全流程实战

简介 生成式AI正以前所未有的速度改变我们的世界&#xff0c;从内容创作到智能客服&#xff0c;再到医疗诊断&#xff0c;它正在成为各行各业的核心驱动力。然而&#xff0c;构建一个高效、安全且负责任的生成式AI系统并非易事。本文将带你从零开始&#xff0c;逐步完成一个完整…

Windows 10更新失败解决方法

在我们使用 Windows 时的时候&#xff0c;很多时候遇到系统更新 重启之后却一直提示“我们无法完成更新&#xff0c;正在撤销更改” 这种情况非常烦人&#xff0c;但其实可以通过修改文件的方法解决&#xff0c;并且正常更新到最新版操作系统 01修改注册表 管理员身份运行注…

ubuntu24.04.2 NVIDIA GeForce RTX 4060笔记本安装驱动

https://www.nvidia.cn/drivers/details/242281/ 上面是下载地址 sudo chmod x NVIDIA-Linux-x86_64-570.133.07.run # 赋予执行权限把下载的驱动复制到家目录下&#xff0c;基本工具准备&#xff0c;如下 sudo apt update sudo apt install build-essential libglvnd-dev …

如何快速下载并安装 Postman?

从下载、安装、启动 Postman 这三个方面为大家详细讲解下载安装 Postman 每一步操作&#xff0c;帮助初学者快速上手。 Postman 下载及安装教程(2025最新)

1.1 计算机网络的概念

首先来看什么是计算机网络&#xff0c;关于计算机网络的定义并没有一个统一的标准&#xff0c;不同的教材有 不同的说法&#xff08;这是王道书对于计算机网络的定义&#xff09;&#xff0c;我们可以结合自己的生活经验去体会这个 定义。 可以用不同类型的设备去连接计算机网络…

Blender绘图——旋转曲线(以LCP与RCP为例)

最近在做左旋圆偏振光&#xff08;LCP&#xff09;与右旋圆偏振光&#xff08;RCP&#xff09;的研究&#xff0c;因此需要画出他们的图&#xff0c;接下来我就介绍一下用Blender怎么去画LCP与RCP。 首先你需要下载Blender软件&#xff0c;网上直接能搜到&#xff0c;图标如下…

Spring与Mybatis整合

持久层整合 1.Spring框架为什么要与持久层技术进行整合 JavaEE开发需要持久层进行数据库的访问操作 JDBC Hibernate Mybatis进行持久层开发存在大量的代码冗余 Spring基于模板设计模式对于上述的持久层技术进行了封装 2.Mybatis整合 SqlSessionFactoryBean MapperScannerConfi…

JDBC FetchSize不生效,批量变全量致OOM问题分析

背景 一个简单的基于 JDBC 采集数据库表的功能&#xff0c;当采集 Postgre SQL 某表&#xff0c;其数据量达到 500万左右的时候&#xff0c;程序一启动就将 JVM 堆内存「6G」干满了。 问题是程序中使用了游标的只前进配置&#xff0c;且设置了 fetchSize 属性&#xff1a; q…

docker - compose up - d`命令解释,重复运行会覆盖原有容器吗

docker - compose up - d`命令解释,重复运行会覆盖原有容器吗 docker - compose up - d 是一个用于管理 Docker 容器的命令,具体含义如下: 命令含义: up:用于创建、启动并运行容器,会根据 docker - compose.yml 文件中定义的服务配置来操作。-d:表示以“分离模式”(det…

A2 最佳学习方法

记录自己想法的最好理由是发现自己的想法&#xff0c;并将其组织成可传播的形式 (The best reason for recording what one thinks is to discover what one thinks and to organize it in transmittable form.) Prof Ackoff 经验之谈&#xff1a; 做培训或者写文章&#xff…

StarRocks 中 CURRENT_TIMESTAMP 和 CURRENT_TIME 分区过滤问题

背景 本文基于Starrocks 3.3.5 最近在进行Starrocks 跑数据的时候&#xff0c;发现了一个SQL 扫描了所有分区的数据&#xff0c;简化后的SQL如下&#xff1a; select date_created from tableA where date_createddate_format(current_time(), %Y-%m-%d %H:%i:%S) limit 20其…