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

每日算法-250526

每日算法学习记录 - 25.05.26

今天记录两道完成的算法题,分享一下解题思路和代码。


面试题 16.24. 数对和

题目描述:
题目图片
设计一个算法,找出数组中两数之和为指定值的所有整数对。一个数只能属于一个数对。

💡 思路

排序 + 双指针

⚙️ 解题过程

这个问题要求我们找出数组中所有和为 target 的数对,并且每个数字只能使用一次。

  1. 排序:首先对数组进行排序。这样做的目的是便于我们使用双指针法,从两端向中间查找。
  2. 双指针
    • 初始化左指针 left 指向数组的开头(索引 0)。
    • 初始化右指针 right 指向数组的末尾(索引 nums.length - 1)。
  3. 遍历和判断
    • left < right 时,持续迭代:
      • 计算当前左右指针指向的两个数 num1 = nums[left]num2 = nums[right] 的和 currentSum = num1 + num2
      • 如果 currentSum == target:找到了一个数对。将 (num1, num2) 加入结果列表。因为每个数只能用一次,所以两个指针都需要移动,left++ 并且 right--,以寻找下一对可能的数对。
      • 如果 currentSum < target:说明当前和太小了,需要增大和。由于数组已排序,左边的数较小,右边的数较大,所以应将左指针 left++ 向右移动,尝试一个更大的 num1
      • 如果 currentSum > target:说明当前和太大了,需要减小和。应将右指针 right-- 向左移动,尝试一个更小的 num2
  4. 返回结果:当 left >= right 时,遍历结束,返回收集到的所有数对。

📈 复杂度

  • 时间复杂度: O ( N log ⁡ N ) O(N \log N) O(NlogN)
    • Arrays.sort(nums) 需要 O ( N log ⁡ N ) O(N \log N) O(NlogN) 时间。
    • 双指针遍历本身需要 O ( N ) O(N) O(N) 时间。
    • 因此,总时间复杂度由排序决定。
  • 空间复杂度: O ( log ⁡ N ) O(\log N) O(logN) O ( N ) O(N) O(N) (取决于排序算法的实现)

💻 Code

class Solution {public List<List<Integer>> pairSums(int[] nums, int target) {// 1. 排序数组Arrays.sort(nums);List<List<Integer>> resultPairs = new ArrayList<>();int left = 0;int right = nums.length - 1;// 2. 双指针遍历while (left < right) {int num1 = nums[left];int num2 = nums[right];int currentSum = num1 + num2;if (currentSum == target) {// 找到了一个数对resultPairs.add(Arrays.asList(num1, num2));// 移动双指针,继续寻找其他数对left++;right--;} else if (currentSum < target) {// 和太小,移动左指针left++;} else {// 和太大,移动右指针right--;}}return resultPairs;}
}

3371. 识别数组中的最大异常值

题目描述:
题目图片
给你一个整数数组 nums。数组中唯一一个不是众数的数字被称为「异常值」。数组的其余所有数字都是相等的「特殊数字」。请你返回「异常值」。

💡 思路

哈希表计数 + 数学推导/枚举

⚙️ 解题过程

题目指出,数组中有一个 “异常值”,其余所有数字都是相等的 “特殊数字”。设特殊数字的值为 s,异常值为 o。如果数组长度为 N,那么有 N-1s1o
数组总和 totalSum = (N-1) * s + o

  1. 预处理
    • 计算数组 nums 中所有元素的总和 sum
    • 使用哈希表 map 存储每个数字及其出现的次数。
  2. 枚举与验证
    • 初始化一个结果变量 ret 为一个足够小的值。
    • 遍历数组中的每一个数 candidateS。我们假设这个 candidateS 就是那个 “特殊数字” s
    • 根据公式 2s + o = sum (其中 scandidateSoexceptionVal),可以推导出潜在的异常值 exceptionVal = sum - 2 * candidateS
  3. 判断与更新
    • 检查计算出的 exceptionVal 是否存在于数组中。
    • 如果 exceptionVal 存在:
      • 情况一:exceptionVal == candidateS
        • 这意味着推断出的异常值和我们假设的特殊数字是同一个值。
        • 此时,要满足 "两个特殊数字 candidateS 和一个异常值 exceptionVal,这确保了至少有两个这样的数字。map.get(candidateS) > 1 是一个必要的条件,确保我们能取出 candidateS 作为特殊值,同时 exceptionVal (也等于 candidateS) 也能在数组中找到。
        • 如果条件满足,更新 ret = Math.max(ret, exceptionVal)
      • 情况二:exceptionVal != candidateS
        • 这意味着异常值和特殊数字是不同的。
        • 我们假设的 candidateS 是特殊数字,exceptionVal 是异常值。
        • 我们只需要 exceptionVal 存在于数组中即可(已通过 map.containsKey(exceptionVal) 检查)。同时,candidateS 作为特殊数字也必须存在 (我们是从 nums 中选取的,所以它肯定存在)。
        • 如果条件满足,更新 ret = Math.max(ret, exceptionVal)
  4. 返回结果:遍历结束后,ret 中存储的就是找到的最大的符合条件的异常值。

📈 复杂度

  • 时间复杂度: O ( N ) O(N) O(N)
    • 计算总和和构建哈希表需要 O ( N ) O(N) O(N) 时间。
    • 遍历数组(或哈希表的键集,最坏情况 N N N 个不同元素)进行检查,每次哈希表操作为 O ( 1 ) O(1) O(1) 平均时间。总共是 O ( N ) O(N) O(N)
  • 空间复杂度: O ( N ) O(N) O(N)
    • 哈希表在最坏情况下可能需要存储 N N N 个不同的数。

💻 Code

class Solution {public int getLargestOutlier(int[] nums) {int largestOutlier = -2001; Map<Integer, Integer> counts = new HashMap<>();long totalSum = 0; for (int x : nums) {totalSum += x;counts.put(x, counts.getOrDefault(x, 0) + 1);}for (int specialNumCandidate : nums) { int potentialOutlier = (int) (totalSum - 2 * (long)specialNumCandidate);if (counts.containsKey(potentialOutlier)) {if (potentialOutlier == specialNumCandidate) {if (counts.get(potentialOutlier) > 1) {largestOutlier = Math.max(largestOutlier, potentialOutlier);}} else {largestOutlier = Math.max(largestOutlier, potentialOutlier);}}}return largestOutlier;}
}

相关文章:

  • 对话魔数智擎CEO柴磊:昇腾AI赋能,大小模型融合开启金融风控新范式
  • python25-递归算法
  • Linux防火墙iptables学习指南!
  • n8n中文版安装指南,使用Docker部署N8N中文版
  • 唯一原生适配鸿蒙电脑的远程控制应用,向日葵正式上线
  • 并发编程艺术--AQS底层源码解析(三)
  • 使用NSIS 和 VNISEdit 打包 electron 程序为 exe 向导式安装包
  • m1 运行renrenfastvue出现的问题和解决方案
  • C 语言学习笔记二
  • 知道Metasploit 吗?
  • 3561.移除相邻字符
  • 【LangChain表达式语言(LCEL)应用实践】
  • 军事大模型及其应用分析
  • TPAMI 2025 | CEM:使用因果效应图解释底层视觉模型
  • 链表面试题10之随机链表的复制
  • MySQL数据库零基础入门教程:从安装配置到数据查询全掌握
  • MySQL增删改查基础教程:熟练掌握DML语句操作【MySQL系列】
  • 58、【OS】【Nuttx】编码规范解读(六)
  • java每日精进 5.26【本地缓存】
  • Java----自动装箱和自动拆包 与 泛型
  • 手机社区网站模板/关键词推广软件排名
  • 萍乡公司做网站/seo技术分享免费咨询
  • 长春个人做网站哪家好/怎样宣传自己的品牌
  • 做电商网站一般需要什么流程/外贸全网营销推广
  • 简述网站推广的基本方法/百度seo原理
  • 三合一网站有必要吗/宁波seo整体优化