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

千问 LeetCode 2122.还原原数组 public int[] recoverArray(int[] nums)

这道题的核心思路是枚举 + 双指针验证。

🧠 解题思路

1. 排序:首先将 nums 数组排序。排序后,最小的元素 nums[0] 必然是原数组某个元素减去 k 得到的(即 lower 数组中的最小值)。
2. 枚举 k:我们遍历排序后的数组,假设 nums[i] (i > 0) 是与 nums[0] 配对的 higher 值。
* 根据定义,higher - lower = 2k,所以 2k = nums[i] - nums[0]。
* 由于 k 必须是正整数,所以 2k 必须是大于 0 的偶数。如果差值是奇数或 0,则跳过。
3. 验证 k:对于每一个可能的 k,我们使用双指针或贪心策略来验证是否能将数组完全配对。
* 每次从未使用的数字中取出最小的一个作为 lower 值。
* 查找是否存在对应的 higher 值(即 lower + 2k)。
* 如果存在,则找到一对,将原数组元素 lower + k 加入结果,并标记这两个数为已使用。
* 如果不存在,说明当前的 k 不合法。
4. 返回结果:一旦找到合法的 k 并成功配对了所有数字,即可返回结果。

💻 Java 代码实现

import java.util.Arrays;

class Solution {
public int[] recoverArray(int[] nums) {
// 1. 排序,方便后续处理
Arrays.sort(nums);
int n = nums.length;

// 2. 枚举可能的 k
// nums[0] 一定是 lower 中的最小值
// 我们枚举 nums[i] 作为与 nums[0] 配对的 higher 值
for (int i = 1; i < n; i++) {
// 优化:如果当前数字和前一个数字相同,跳过,避免重复计算
if (nums[i] == nums[i - 1]) continue;

// 计算 2k
int diff = nums[i] - nums[0];

// k 必须是正整数,所以 2k 必须是正偶数
if (diff <= 0 || diff % 2 != 0) continue;

int k = diff / 2;

// 3. 尝试用当前的 k 还原数组
int[] result = tryRecover(nums, k);
if (result != null) {
return result;
}
}

return new int[0]; // 理论上不会执行到这里,因为题目保证有解
}

private int[] tryRecover(int[] nums, int k) {
int n = nums.length;
boolean[] used = new boolean[n]; // 标记数组,记录元素是否已被使用
int[] result = new int[n / 2];
int resultIdx = 0;

// 使用双指针贪心匹配
// 每次找未使用的最小值作为 lower,然后找对应的 higher
for (int i = 0; i < n; i++) {
if (used[i]) continue; // 如果当前数已使用,跳过

int lower = nums[i];
int higher = lower + 2 * k; // 对应的 higher 值

// 寻找 higher
boolean found = false;
for (int j = i + 1; j < n; j++) {
if (!used[j] && nums[j] == higher) {
// 找到配对
used[i] = true;
used[j] = true;
result[resultIdx++] = lower + k; // 原数组元素是 (lower + higher) / 2
found = true;
break;
}
}

// 如果找不到配对的 higher,说明当前 k 不合法
if (!found) {
return null;
}
}

return result;
}
}

📝 复杂度分析

* 时间复杂度:O(n² log n) 或 O(n²)。
* 排序需要 O(n log n)。
* 外层循环最多执行 O(n) 次。
* 内层 tryRecover 函数在最坏情况下需要 O(n²) 的时间(对于每个未使用的元素,都要向后查找配对)。
* 总体时间复杂度为 O(n log n + n³),但在实际运行中,由于一旦找到合法的 k 就会立即返回,所以通常会更快。更精确的分析是 O(n²),因为内层循环的总操作次数是线性的。
* 空间复杂度:O(n),主要用于 used 数组和排序的栈空间。

http://www.jsqmd.com/news/767821/

相关文章:

  • 移植代码后LED灯都不闪了?可能是VTOR向量表地址在捣鬼(附STM32CubeIDE与Keil排查步骤)
  • Ising机与Bounce-Bind机制在组合优化中的应用
  • 构建可移植开发环境:配置仓库与自动化部署实践
  • 机械操作耗尽精力?dothething:一款全自主本地 AI 代理,替你接管系统控制与网络任务
  • RTX 3050 + Win11实测:Python 3.10环境下,用pip搞定TensorFlow-GPU 2.10.1的完整避坑指南
  • OpencvSharp 算子学习教案之 - Cv2.GetStructuringElement 重载1
  • STM32F103C8T6硬件SPI驱动W25Q64 Flash全流程(附完整工程代码)
  • C#基础(持续更新中)
  • Python初学者项目练习9--对简单列表元素排序
  • 解决ZYNQ裸机网络扩展难题:为LWIP库添加自定义PHY驱动与SDK配置界面
  • Windows系统光标深度替换:INF方案实现macOS指针移植与优化
  • AI编码助手统一配置工具agent-dotfiles:告别重复配置,实现规则与技能一键同步
  • BrowserClaw:基于Puppeteer与Playwright的浏览器自动化与数据抓取实践
  • AI工具搭建自动化视频生成图像缩放
  • ChatGPT文档格式化指令:打造Google Docs无缝协作的AI写作规范
  • GRADFILTERING:基于梯度信噪比的指令调优数据筛选方法
  • 别再死记硬背async/await了!用Playwright+Python写自动化脚本,这3个坑我帮你踩过了
  • 千问 LeetCode 2127.参加会议的最多员工数 public int maximumInvitations(int[] favorite)
  • 解释器模式是行为型设计模式的一种,其核心思想是给定一个语言,定义它的文法的一种表示
  • STM32G431RBT6的HAL库避坑指南:蓝桥杯嵌入式那些CubeMX没告诉你的细节
  • 构建本地化音视频转录分析平台:Whisper+Ollama+Meilisearch实战
  • SolidGPT实战指南:基于语义搜索的代码与文档智能问答系统
  • 避坑指南:SAP固定资产配置里,记账码70和31千万别乱选!附SPRO完整路径
  • 想在Win10任务栏显示秒数?试试用StartAllBack配合注册表修改(附详细步骤)
  • 【Redis】Redis——过期键删除策略、内存淘汰8种策略、LRU/LFU实现
  • 秒级推演赋能复杂场景,镜像视界夯实工业数字根基
  • SpringBoot + Thymeleaf 实战:手把手教你从零搭建一个婚纱租赁网站(附完整源码)
  • PageIndex:基于RAG的网页智能知识库构建实战指南
  • HoRain云--超全PHP安装指南:Linux/Windows/macOS全攻略
  • MQTTX与AI助手实时交互:基于MCP与SSE的物联网协议桥接实践