当前位置: 首页 > article >正文

每日算法-250326

83. 删除排序链表中的重复元素

题目描述

Problem 83 Description

思路

使用快慢指针遍历排序链表。slow 指针指向当前不重复序列的最后一个节点,fast 指针用于向前遍历探索。当 fast 找到一个与 slow 指向的节点值不同的新节点时,就将 slownext 指向 fast,然后 slow 前进。

解题过程

  1. 处理边界情况:如果链表为空 (head == null),直接返回 null
  2. 初始化指针:定义 slowfast 指针,都初始化为 head
  3. 遍历链表:使用 while 循环,条件是 fast != nullslow 不会是 null 因为它总是在 fast 或其之前)。
    • 在循环中,移动 fast 指针向前探索。
    • 判断重复:如果 fast.val != slow.val,说明 fast 指向的节点是一个新的不重复元素。
    • 更新链表:此时,将 slownext 指针指向 fast (slow.next = fast),然后将 slow 指针也向前移动一步 (slow = slow.next)。
    • 无论是否找到不重复元素,fast 指针都需要在每次迭代中向前移动 (fast = fast.next)。
  4. 断开尾部链接:循环结束后,slow 指向的是新链表的最后一个节点。为了确保链表正确终止,需要将 slownext 设置为 null (slow.next = null)。这会断开与后面可能存在的重复元素的连接。
  5. 返回结果:返回原始的 head,因为头节点可能没变,或者即使变了,head 变量仍然指向修改后链表的起始位置。

复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是链表的节点数。因为 fast 指针遍历整个链表一次。
  • 空间复杂度: O ( 1 ) O(1) O(1),只使用了常数级别的额外空间(两个指针)。

Code (Java)

/*** 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 deleteDuplicates(ListNode head) {if (head == null) {return head; // 或者 return null,效果一样}ListNode slow = head, fast = head;// fast 指针用于遍历while (fast != null) {// 当 fast 遇到与 slow 不同的值时if (fast.val != slow.val) {// slow 的下一个节点指向 fast 这个不重复的节点slow.next = fast;// slow 移动到新的不重复节点位置slow = slow.next;}// fast 继续向后遍历fast = fast.next;}// 循环结束后,slow 是最后一个不重复节点,断开其后的链接slow.next = null;return head;}
}

904. 水果成篮

题目描述

Problem 904 Description

思路

这是一道典型的滑动窗口问题。目标是找到一个最长的子数组,其中最多包含两种不同的元素。

我们可以使用一个哈希表(或者利用题目 0 <= fruits[i] < fruits.length 的条件,使用一个数组 hash)来记录窗口内每种水果出现的次数。同时,用一个变量 count 记录窗口内不同水果的种类数量。

解题过程

  1. 初始化
    • ret = 0: 用于存储最长子数组的长度(即最多能收集的水果数)。
    • count = 0: 记录当前窗口内不同水果的种类数。
    • n = fruits.length: 数组长度。
    • hash = new int[n]: 使用数组作为哈希表,hash[i] 存储水果 i 在当前窗口内的数量。
    • left = 0, right = 0: 滑动窗口的左右边界。
  2. 扩展窗口(右移 right
    • right 指针向右移动,考察 fruits[right] 这个水果,令 in = fruits[right]
    • 更新计数:如果 hash[in] == 0,说明这是窗口内第一次遇到这种水果,因此不同水果种类数 count 增加 1。
    • in 水果的计数加 1:hash[in]++
  3. 收缩窗口(右移 left
    • 判断条件:当 count > 2 时,表示窗口内的水果种类超过了 2 种,此时窗口不满足条件,需要收缩。
    • 处理出窗口元素:令 out = fruits[left]
    • out 水果的计数减 1:hash[out]--
    • 更新计数:如果 hash[out] == 0,说明移除这个水果后,窗口内不再有这种类型的水果了,因此不同水果种类数 count 减少 1。
    • 左边界 left 向右移动:left++
    • 这个收缩过程(while (count > 2))会持续进行,直到窗口重新满足 count <= 2 的条件。
  4. 更新结果:在每次移动 right 之后(并且窗口调整为合法状态后),当前窗口 [left, right] 是合法的(最多包含两种水果)。计算当前窗口的长度 right - left + 1,并更新 ret = Math.max(ret, right - left + 1)
  5. 循环结束:当 right 到达数组末尾时,循环结束。
  6. 返回结果:返回 ret

复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 fruits 的长度。左右指针 leftright 都最多遍历数组一次。
  • 空间复杂度: O ( n ) O(n) O(n),在最坏情况下(例如所有水果种类都不同,但这里水果种类数受限于数组长度 n),用于存储水果计数的 hash 数组需要 O ( n ) O(n) O(n) 的空间。如果水果种类数远小于 n,可以认为是 O ( C ) O(C) O(C),其中 C C C 是水果种类的数量上限。

Code (Java)

class Solution {public int totalFruit(int[] fruits) {int ret = 0, count = 0;int n = fruits.length;// 利用题目条件,可以使用数组代替 HashMapint[] hash = new int[n];for (int left = 0, right = 0; right < n; right++) {// 元素进入窗口int in = fruits[right];// 如果是新水果种类,count增加if (hash[in] == 0) {count++;}// 该水果数量增加hash[in]++;// 如果水果种类超过2种,需要收缩窗口while (count > 2) {// 元素离开窗口int out = fruits[left];// 该水果数量减少hash[out]--;// 如果移除后该水果数量为0,说明少了一种水果if (hash[out] == 0) {count--;}// 左指针右移left++;}// 窗口调整完毕后,更新最大长度ret = Math.max(ret, right - left + 1);}return ret;}
}

1695. 删除子数组的最大得分

题目描述

Problem 1695 Description

思路

这个问题要求找到一个元素唯一的子数组,使其元素和最大。这同样可以用滑动窗口解决。

我们需要维护一个窗口,确保窗口内的所有元素都是唯一的。可以使用一个哈希表 (HashMap) 来记录窗口内每个数字出现的次数。同时,维护一个变量 sum 记录当前窗口内元素的和。

解题过程

  1. 初始化
    • ret = 0: 用于存储最大得分(即元素唯一的子数组的最大和)。
    • sum = 0: 当前窗口内元素的和。
    • hash = new HashMap<>(): 记录窗口内数字及其出现次数。
    • left = 0, right = 0: 滑动窗口的左右边界。
  2. 扩展窗口(右移 right
    • right 指针向右移动,考察 nums[right],令 in = nums[right]
    • 更新窗口和sum += in
    • 更新哈希表:将 in 的计数加 1。hash.put(in, hash.getOrDefault(in, 0) + 1)
  3. 收缩窗口(右移 left
    • 判断条件:当 hash.get(in) > 1 时,表示新加入的元素 in 在窗口内出现了重复,窗口不再满足“元素唯一”的条件,需要收缩。
    • 处理出窗口元素:令 out = nums[left]
    • 更新窗口和sum -= out
    • 更新哈希表:将 out 的计数减 1。hash.put(out, hash.get(out) - 1)
    • 左边界 left 向右移动:left++
    • 这个收缩过程 (while (hash.get(in) > 1)) 会持续进行,直到窗口内 in 的计数变回 1(即窗口内不再有重复的 in)。
  4. 更新结果:在每次移动 right 之后,窗口 [left, right] 必然是元素唯一的(因为收缩步骤保证了这一点)。此时,当前窗口的和 sum 是一个有效的得分。更新 ret = Math.max(ret, sum)
  5. 循环结束:当 right 到达数组末尾时,循环结束。
  6. 返回结果:返回 ret

复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums 的长度。左右指针 leftright 都最多遍历数组一次。哈希表操作平均时间复杂度为 O ( 1 ) O(1) O(1)
  • 空间复杂度: O ( n ) O(n) O(n),在最坏情况下(例如数组中所有元素都不同),哈希表需要存储 O ( n ) O(n) O(n) 个元素。如果数组中不同元素的数量上限为 U U U,则空间复杂度为 O ( min ⁡ ( n , U ) ) O(\min(n, U)) O(min(n,U))

Code (Java)

import java.util.HashMap;
import java.util.Map;class Solution {public int maximumUniqueSubarray(int[] nums) {int ret = 0, sum = 0;Map<Integer, Integer> hash = new HashMap<>();for (int left = 0, right = 0; right < nums.length; right++) {// 元素进入窗口int in = nums[right];// 更新窗口和sum += in;// 更新元素计数hash.put(in, hash.getOrDefault(in, 0) + 1);// 如果窗口内出现重复元素 (刚加入的 in 导致重复)while (hash.get(in) > 1) {// 元素离开窗口int out = nums[left];// 更新窗口和sum -= out;// 更新元素计数hash.put(out, hash.get(out) - 1);// 左指针右移left++;}// 此时窗口内元素唯一,更新最大得分ret = Math.max(ret, sum);}return ret;}
}

1423. 可获得的最大点数(复习)

题目描述

Problem 1423 Description

复习思路

这道题要求从数组两端取走总共 k 张牌,使得分数总和最大。

这个问题可以转化为:找到数组中间连续 n - k 个元素,使其和最小。因为数组总和是固定的,要让两端 k 个元素的和最大,等价于让中间 n - k 个元素的和最小。

因此,我们可以使用滑动窗口来找到长度为 m = n - k 的子数组的最小和。

解题过程(滑动窗口找最小和)

  1. 计算窗口大小:计算中间部分的长度 m = n - k
  2. 处理特殊情况:如果 m == 0(即 n == k),说明需要取走所有卡牌,直接计算并返回整个数组的总和。
  3. 初始化
    • totalSum = 0: 整个数组的总和。
    • windowSum = 0: 当前滑动窗口(长度为 m)的和。
    • minWindowSum = Integer.MAX_VALUE: 用于记录所有长度为 m 的窗口中,和的最小值。
    • left = 0: 窗口左边界。
  4. 遍历数组与滑动窗口
    • 使用 right 指针从 0 遍历到 n-1
    • 累加总和totalSum += cardPoints[right]
    • 累加窗口和windowSum += cardPoints[right]
    • 维护窗口大小:当窗口达到大小 m 时(即 right - left + 1 == mright >= m - 1),开始执行以下操作:
      • 更新最小窗口和minWindowSum = Math.min(minWindowSum, windowSum)
      • 收缩窗口:从 windowSum 中减去最左边的元素 cardPoints[left]
      • 移动左边界left++
  5. 计算结果:遍历结束后,minWindowSum 存储了长度为 n - k 的子数组的最小和。最终结果为 totalSum - minWindowSum

复杂度

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 cardPoints 的长度。只需要遍历数组一次。
  • 空间复杂度: O ( 1 ) O(1) O(1),只使用了常数级别的额外空间。

Code (Java)

class Solution {public int maxScore(int[] cardPoints, int k) {int n = cardPoints.length;int m = n - k; // 中间要保留的元素个数 (窗口大小)int totalSum = 0; // 数组总和int windowSum = 0; // 当前窗口的和// ret 在这里用来存储长度为 m 的窗口的最小和int minWindowSum = Integer.MAX_VALUE;// 特殊情况:k == n, m == 0if (m == 0) {for (int point : cardPoints) {totalSum += point;}return totalSum;}for (int left = 0, right = 0; right < n; right++) {// 累加当前元素到窗口和windowSum += cardPoints[right];// 同时累加到总和 (只需计算一次)totalSum += cardPoints[right];// 当窗口大小达到 m 时if (right - left + 1 >= m) {// 更新最小窗口和minWindowSum = Math.min(minWindowSum, windowSum);// 从窗口和中移除最左边的元素windowSum -= cardPoints[left];// 左指针右移,保持窗口大小left++;}}// 最大得分 = 总和 - 中间 m 个元素的最小和// 注意: 如果 m > n (k < 0) 或 m < 0 (k > n) 是无效输入, 但题目保证 1 <= k <= cardPoints.length// 如果 m=n (k=0), minWindowSum 应该等于 totalSum,结果是 0 (逻辑上正确,但未覆盖 m=0 的代码路径)// minWindowSum 如果没被更新过(例如 m > n), 结果会出错, 但题目约束避免了此情况。// 在 m > 0 时,minWindowSum 一定会被更新。return totalSum - minWindowSum;}
}

相关文章:

每日算法-250326

83. 删除排序链表中的重复元素 题目描述 思路 使用快慢指针遍历排序链表。slow 指针指向当前不重复序列的最后一个节点&#xff0c;fast 指针用于向前遍历探索。当 fast 找到一个与 slow 指向的节点值不同的新节点时&#xff0c;就将 slow 的 next 指向 fast&#xff0c;然后 …...

trino查询mysql报Unknown or incorrect time zone: ‘Asia/Shanghai‘

问题 trino查询mysql时报Error listing schemas for catalog mysql: java.sql.SQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.&#xff0c;trino的日志中看到Unknown or incorrect time zone…...

java学习笔记7——面向对象

关键字&#xff1a;static 类变量 静态变量的内存解析&#xff1a; 相关代码&#xff1a; public class ChineseTest {public static void main(String[] args) {System.out.println(Chinese.nation); //null 没赋值前System.out.println(Chinese.nation); //中国 静态变量赋值…...

leetcode day31 453+435

453 用最少数量引爆气球 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可以沿着 x 轴从不同点 完全垂直 地…...

C++三大特性之继承

1.继承的概念及定义 回忆封装 C Stack类设计和C设计Stack对比。封装更好&#xff1a;访问限定符类的数据和方法放在一起 -> 避免底层接口的暴露&#xff0c;数据更加的安全&#xff0c;程序的耦合性更高迭代器的设计&#xff0c;封装了容器底层结构&#xff0c;在不暴露底层…...

PyQt QDoubleSpinBox控件用法详解

QDoubleSpinBox 是 PyQt中用于输入浮点数的控件&#xff0c;支持键盘输入和上下箭头调整数值。与QtSpinBox不同&#xff0c;QtSpinBox是用于输入整数的控件。 关键属性和方法 QDoubleSpinBox 的关键属性和方法如下表所示&#xff1a; 方法/属性说明setRange(min, max)设置数…...

解决Vmware 运行虚拟机Ubuntu22.04卡顿、终端打字延迟问题

亲测可用 打开虚拟机设置&#xff0c;关闭加速3D图形 &#xff08;应该是显卡驱动的问题&#xff0c;不知道那个版本的驱动不会出现这个问题&#xff0c;所以干脆把加速关了&#xff09;...

查询Marklogic数据库,因索引配置造成的返回数据count不同的问题

查询Marklogic数据库&#xff0c;因索引配置造成的返回数据count不同的问题 一&#xff0c;问题&#xff1a; 目前由两个MarkLogic DB&#xff0c;其中A表示所有的数据库统称&#xff0c;包含于BCD&#xff1b; 调用查询接口&#xff0c;通过A和B入口且相同的查询条件去查询B…...

ctfshow做题笔记—栈溢出—pwn73、pwn74

目录 一、pwn73(愉快的尝试一下一把梭吧&#xff01;) 二、pwn74(噢&#xff1f;好像到现在为止还没有了解到one_gadget?) 前言&#xff1a; 抽空闲时间继续学习&#xff0c;记录了两道题&#xff0c;pwn74卡了几天哈哈。 一、pwn73(愉快的尝试一下一把梭吧&#xff01;) …...

026-zstd

zstd 以下为Zstandard&#xff08;zstd&#xff09;压缩算法从原理到代码实现的技术调研报告&#xff0c;结合流程图、结构图及完整C代码实现&#xff1a; 一、核心原理与技术架构 1.1 算法原理 Zstd基于LZ77衍生算法与熵编码&#xff08;FSE/Huffman&#xff09;的混合架构&…...

AF3 quat_to_rot函数解读

AlphaFold3 rigid_utils 模块的 quat_to_rot 函数的功能是把四元数转换为旋转矩阵,函数利用预定义的四元数到旋转矩阵的转换表 _QTR_MAT 来简化计算。 理解四元数到旋转矩阵的转换 源代码: _quat_elements = ["a", "b", "c", "d"]…...

Elasticsearch 的搜索功能

Elasticsearch 的搜索功能 建议阅读顺序&#xff1a; Elasticsearch 入门Elasticsearch 搜索&#xff08;本文&#xff09; 1. 介绍 使用 Elasticsearch 最终目的是为了实现搜索功能&#xff0c;现在先将文档添加到索引中&#xff0c;接下来完成搜索的方法。 查询的分类&…...

Vala编成语言教程-构造函数和析构函数

构造函数 Vala支持两种略有不同的构造方案&#xff1a;我们将重点讨论Java/C#风格的构造方案&#xff0c;另一种是GObject风格的构造方案。 Vala不支持构造函数重载的原因与方法重载不被允许的原因相同&#xff0c;这意味着一个类不能有多个同名构造函数。但这并不构成问题&…...

Mybatis-plus配置动态多数据源

前言&#xff1a;微服务架构中&#xff0c;有些模块中可能不同组件用不同数据源&#xff0c;或者做数据库主从集群需要读写分离&#xff0c;动态切换数据源&#xff0c;或不同方法需要不同数据源就需要一个快捷方便的方法。引用动态数据源组件dynamic-datasource-spring-boot-s…...

CSS+JS 堆叠图片动态交互切换

结合DeepSeek提供的代码&#xff0c;终于实现了堆叠两张图片动态循环切换&#xff0c;以下是代码&#xff1a; 通过绝对定位放了两张图片 <div class"col-lg-5" style"z-index: 40; position: relative;"><img src"images/banner_1.png&quo…...

内存检查之Valgrind工具

内存检查之Valgrind工具 Author: Once Day Date: 2025年3月26日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章请查看专栏: Linux实践记录_Once-Day的博客-CSD…...

强大的AI网站推荐(第四集)—— Gamma

网站&#xff1a;Gamma 号称&#xff1a;展示创意的新媒介 博主评价&#xff1a;快速展示创意&#xff0c;重点是展示&#xff0c;在几秒钟内快速生成幻灯片、网站、文档等内容 推荐指数&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x…...

javafx项目结构+代码规范

javafx项目 1. 新建项目&#xff0c;对项目的理解 jdk&#xff1a; 是 Java Development ToolKit 的简称&#xff0c;也就是 Java 开发工具包。JDK 是整个 Java 的核心&#xff0c;包括 Java 运行环境&#xff08;Java Runtime Envirnment&#xff0c;简称 JRE&#xff09;&a…...

国外计算机证书推荐(考证)(6 Sigma、AWS、APICS、IIA、Microsoft、Oracle、PMI、Red Hat)

文章目录 证书推荐1. 六西格玛 (6 Sigma)2. 亚马逊网络服务 (AWS)3. 美国生产与库存控制学会 (APICS)4. 内部审计师协会 (IIA)5. 微软 (Microsoft)6. 甲骨文 (Oracle)7. 项目管理协会 (PMI)8. 红帽 (Red Hat) 证书推荐 1. 六西格玛 (6 Sigma) 介绍&#xff1a;六西格玛是一种…...

黑盒测试与白盒测试详解

黑盒测试和白盒测试是软件测试中两种最基本的测试方法&#xff0c;它们在测试视角、测试重点和适用场景等方面存在显著差异。 一、黑盒测试 1. 基本概念 黑盒测试又称功能测试&#xff0c;将软件视为一个"黑盒子"&#xff0c;不关心内部结构和实现细节&#xff0c;只…...

准确--配置服务器文件数

某些系统可能在 /etc/security/limits.d/ 目录下有额外配置覆盖全局设置。检查是否存在冲突文件&#xff1a; ls /etc/security/limits.d/如果有文件&#xff08;如 90-nproc.conf 或 90-nofile.conf&#xff09;&#xff0c;需编辑或删除这些文件中的冲突配置。 确保系统启用…...

《熔化焊接与热切割作业》考试注意事项

考试前的准备 携带必要的证件和材料&#xff1a;考生需携带身份证、准考证等有效证件&#xff0c;以及考试所需的焊接工具、材料等。确保证件齐全&#xff0c;避免因证件问题影响考试。 提前检查焊接设备和工具&#xff1a;在考试前&#xff0c;考生应仔细检查焊接设备和工具是…...

ROS2的发展历史、核心架构和应用场景

以下是对**ROS2&#xff08;Robot Operating System 2&#xff09;**的发展历史、核心架构和应用场景的详细解析&#xff0c;覆盖其技术演变、关键特性和生态系统&#xff1a; 一、ROS2的诞生背景&#xff1a;从ROS1到ROS2 1. ROS1的历史与局限 ROS1的起源&#xff1a; 2007年…...

[unity 点击事件] 区域响应点击事件,排除子节点区域,Raycast Target 应用

当我打开一个二级弹窗后&#xff0c;希望可以通过点击弹窗以外的区域来关闭该弹窗。一开始我是在弹窗主节点上挂载了一个 button 组件&#xff0c;该 button 注册的点击事件中关闭该弹窗。在子节点&#xff08;一个背景图&#xff09;的image组件上启用 Raycast Target 选项&am…...

鸿蒙生态全解析:应用适配分享

一、鸿蒙系统的技术底座与适配挑战 HarmonyOS NEXT 作为全场景分布式操作系统&#xff0c;通过统一的技术底座和声明式开发框架&#xff0c;实现了 "一次开发&#xff0c;多端部署" 的跨设备协同能力。其核心优势在于&#xff1a; 弹性部署架构&#xff1a;一套系统…...

el-select 可搜索下拉框 在ios、ipad 无法唤出键盘,造成无法输入

下一篇&#xff1a;el-select 可搜索下拉框&#xff0c;选中选项后&#xff0c;希望立即失去焦点&#xff0c;收起键盘&#xff0c;执行其他逻辑 【效果图】&#xff1a;分组展示选项 >【去界面操作体验】 首先&#xff0c;通过 夸克浏览器的搜索: el-select 在 ipad 输入框…...

深度剖析:域名与DNS安全的全方位解读

导语 在互联网的庞大体系中,域名如同我们访问网络资源的“门牌号”,而DNS则像是将门牌号翻译为具体地址的“翻译官”。然而,这看似平常的域名与DNS系统,却面临着诸多安全风险。一旦遭受攻击,可能导致网站无法访问、用户数据泄露等严重后果。了解域名与DNS安全知识,对保障…...

使用ZMQ和protobuf实现C++程序与Python程序的通信

文章目录 背景一 应用场景与需求二 Protobuf: 跨语言数据交换的基石三 通信方案 ZMQ (ZeroMQ) —— 高性能消息中间件四 进阶: 安全性与性能优化五 实践例子: 工厂温度监控系统5.1 场景描述5.2 Protobuf数据结构定义5.3 C数据采集与发布5.4 Python数据接收与可视化5.5 关键实现…...

Linux实现生产者消费者模型

目录 概念及优势 代码实现 概念及优势 生产者消费者模型是一种用于线程同步的模型&#xff0c;在这个模型中有两种角色&#xff0c;生产者生产数据&#xff0c;消费者消费数据。有三种关系&#xff0c;生产者与生产者&#xff0c;消费者与消费者&#xff0c;生产者与消费者。…...

AI驱动下的智能异常处置:海量多元异构数据的挑战与应对

摘要 在QCon北京会议上&#xff0c;AI驱动的智能异常处置成为焦点。会议深入探讨了平台复杂性及处理海量多元异构数据时所面临的挑战&#xff0c;特别是异常识别与根本原因定位的难题。这些挑战要求技术从业者不断优化算法&#xff0c;以提升数据处理效率和准确性。 关键词 …...