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

LeetCode算法日记 - Day 21: 消失的两个数字、替换所有的问号

目录

1. 消失的两个数字

1.1 题目解析

1.2 解法

1.3 代码实现

2. 替换所有的问号

2.1 题目解析

2.2 解法

2.3 代码实现


1. 消失的两个数字

面试题 17.19. 消失的两个数字 - 力扣(LeetCode)

给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。你能在 O(N) 时间内只用 O(1) 的空间找到它们吗?

以任意顺序返回这两个数字均可。

示例 1:

输入:[1]
输出:[2,3]

示例 2:

输入:[2,3]
输出:[1,4]

提示:

  • nums.length <= 30000

1.1 题目解析

这是一个「两类经典题目的结合体」:

  • 只出现一次的数字 III → 提供了分组筛选的思路:利用异或和最低位不同的二进制位,把数组划分成两组,再各自异或出答案。

  • 丢失的数字 → 提供了范围取值的思路:通过 1..N 和数组对比,利用位运算抵消信息,最终定位缺失或特殊的数字。

换句话说:

  • 我们先要找到两个“落单数”整体的异或值。

  • 然后借助「分组异或」手法,把它们拆分出来。

如果没有做过这两道题请移步到本博主的这两篇博客日记,会有更详细的解答。

LeetCode算法日记 - Day 18: 只出现一次的数字、只出现一次的数字III-CSDN博客

LeetCode算法日记 - Day 19:判定字符是否唯一、丢失的数字-CSDN博客

常规解法
哈希表统计频次 → 直接返回出现一次的两个数字。

  • 时间:O(n),空间:O(n),虽然能过,但不符合题目要求(必须 O(1) 空间)。

  • 所以必须转向「位运算」这一类对数值分布敏感的解法。

思路转折
要在 O(1) 空间下解决:

  • 必须让数组里成对的数字能自动抵消。

  • 异或运算正好具备这个特性:x ^ x = 0,0 ^ y = y。

  • 于是整体异或得到 a ^ b,再用最低位的不同点分组,就能单独求出 a 和 b。

这就是「只出现一次的数字 III」的核心思想,而能联想到用异或抵消,其实也是源自「丢失的数字」给过的启发。

1.2 解法

  • 整体异或 → 得到两个只出现一次数字的异或值。

  • 利用最低位的不同二进制位,区分出这两个数字。

  • 分组异或 →单独得到 a 和 b。

i)tmp = 0,遍历数组:tmp ^= num,for循环 tmp^i 也就是完整范围部分,遍历 i

 的长次数是 nums 长度+2,最终得到 tmp = a ^ b。

ii)mark = Integer.lowestOneBit(tmp) → 取出最低的一个二进制 1。 。

iii)再遍历数组:

  • (num & mark) == 0 的分到一组,整体异或得到 a。

  • (num & mark) != 0 的分到另一组,整体异或得到 b。

  • (i & mark) == 0 分到一组,整体异或得到 a。

  • (i & mark) != 0 分到一组,整体异或得到 b。

iiii)返回 [a, b]。

1.3 代码实现

class Solution {public int[] singleNumber(int[] nums) {// 第一次整体异或,得到 a ^ bint tmp = 0;for (int num : nums) {tmp ^= num;}// 找到最低位不同的标志位int mark = Integer.lowestOneBit(tmp);// 分组异或int a = 0, b = 0;for (int num : nums) {if ((num & mark) == 0) {a ^= num;} else {b ^= num;}}return new int[]{a, b};}
}

复杂度分析

  • 时间复杂度:O(n),两次线性扫描。

  • 空间复杂度:O(1),只用常量存储。

2. 替换所有的问号

1576. 替换所有的问号 - 力扣(LeetCode)

给你一个仅包含小写英文字母和 '?' 字符的字符串 s,请你将所有的 '?' 转换为若干小写字母,使最终的字符串不包含任何 连续重复 的字符。

注意:你 不能 修改非 '?' 字符。

题目测试用例保证  '?' 字符 之外,不存在连续重复的字符。

在完成所有转换(可能无需转换)后返回最终的字符串。如果有多个解决方案,请返回其中任何一个。可以证明,在给定的约束条件下,答案总是存在的。

示例 1:

输入:s = "?zs"
输出:"azs"
解释:该示例共有 25 种解决方案,从 "azs" 到 "yzs" 都是符合题目要求的。只有 "z" 是无效的修改,因为字符串 "zzs" 中有连续重复的两个 'z' 。

示例 2:

输入:s = "ubv?w"
输出:"ubvaw"
解释:该示例共有 24 种解决方案,只有替换成 "v" 和 "w" 不符合题目要求。因为 "ubvvw" 和 "ubvww" 都包含连续重复的字符。

2.1 题目解析

题目本质

  • 输入一个只包含小写字母和 '?' 的字符串。

  • 需要将 '?' 替换为小写字母,使得最终字符串不包含连续重复字符

  • 保证原有非 '?' 字符本身没有连续重复。

可以抽象为:在字符串中找到“空位”,选择合法字符填充,使左右字符不重复的问题

常规解法

  • 遍历字符串,遇到 '?' 随意填充一个字母。

  • 检查替换后是否出现连续重复字符,如果有则重新尝试。

  • 这种方法简单,但每次都要回溯检查,最坏情况下复杂度高达 O(26^k),k 为 '?' 数量。

  • 当 '?' 较多时,效率低下。

思路转折

  • 发现规律:每个 '?' 只需考虑左右相邻字符

  • 因为题目保证原始字符串没有连续重复,所以只需保证填入的字符 ≠ 左右邻居即可。

  • 不必回溯、多次尝试,直接顺序填充即可。

  • 这样复杂度可降到 O(n)。

2.2 解法

算法思路:

  • 顺序遍历字符串。

  • 遇到 '?',从 'a' 到 'z' 遍历,选择不等于左边或右边字符的字母填充。

  • 每次填充后立即停止当前 '?' 的选择,保证不会和左右重复。

i)将字符串转换为字符数组,便于修改。

ii)遍历字符数组:

  • 如果当前字符不是 '?' → 跳过。

  • 如果是 '?' → 从 'a' 到 'z' 找一个合法字符 c:

    • 左边合法:i==0 || ch[i-1] != c

    • 右边合法:i==ch.length-1 || ch[i+1] != c

    • 若左右都合法 → 填充 c,并 break。

iii)遍历结束后,将字符数组转换回字符串并返回。

2.3 代码实现

class Solution {public String modifyString(String s) {char[] ch = s.toCharArray();for (int i = 0; i < ch.length; i++) {if (ch[i] == '?') {for (char c = 'a'; c <= 'z'; c++) {boolean leftOk = (i == 0 || ch[i - 1] != c);boolean rightOk = (i == ch.length - 1 || ch[i + 1] != c);if (leftOk && rightOk) {ch[i] = c;break;}}}}return new String(ch);}
}

复杂度分析

  • 时间复杂度:O(n),每个字符最多尝试 26 种字母。

  • 空间复杂度:O(n),用于存储字符数组。

http://www.dtcms.com/a/350343.html

相关文章:

  • 解决 Ubuntu 环境下 ffmpeg 安装依赖问题(FileNotFoundError: ffprobe 错误处理)
  • 信号处理的核心机制:从保存、处理到可重入性与volatile
  • 做市商在期权市场中的盈利模式是什么?
  • 挖币与区块链技术有怎样的联系?
  • 【大白话解析】 OpenZeppelin 的 ECDSA 库:以太坊签名验证安全工具箱(附源代码)
  • ElasticSearch数据库(ES数据库)是什么???
  • docker安装ros
  • 网络编程1-基本概念、函数接口
  • 页面中嵌入Coze的Chat SDK
  • Hazelcast
  • Docker:数据卷(挂载本地目录)
  • FFmpeg 8.0 “Huffman“ 全面评测:Vulkan 加速、AI 集成与编解码革新
  • 8月25日
  • UPROPERTY的再次学习
  • 高通SNPE测试:6、在开发板上运行Inception v3 Model(oe-linux)
  • vite + react + tailwind(2025-08-25)
  • C++贪吃蛇---详细步骤
  • 2.4 Flink运行时架构:Task、SubTask、ExecutionGraph的关系
  • OPcache 高级技术文档:原理、监控与优化实践
  • Unity使用Sprite切割大图
  • JavaScript 性能优化实战:从理论到落地的技术文章大纲
  • 基于长短期记忆网络的多变量时间序列预测 LSTM
  • Redis 哨兵 Sentinel
  • 【沉浸式解决问题】NVIDIA 显示设置不可用。 您当前未使用连接到NVIDIA GPU 的显示器。
  • 实时监测蒸汽疏水阀的工作状态的物联网实时监控平台技术解析
  • VLLM的加速原理
  • 基于MATLAB实现支持向量机(SVM)进行预测备
  • 大模型的多机多卡训练
  • 神经网络|(十五)概率论基础知识-协方差标准化和皮尔逊相关系数
  • 亚马逊AWD美西新仓上线:旺季备货的效率革命与策略升级