代码随想录-Day07

454. 四数相加 II

给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0

示例 1:

输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
输出:2
解释:
两个元组如下:

  1. (0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
  2. (1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0
class Solution {public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {Map<Integer, Integer> countAB = new HashMap<Integer, Integer>();for (int u : A) {for (int v : B) {countAB.put(u + v, countAB.getOrDefault(u + v, 0) + 1);}}int ans = 0;for (int u : C) {for (int v : D) {if (countAB.containsKey(-u - v)) {ans += countAB.get(-u - v);}}}return ans;}
}

这段代码定义了一个名为 Solution 的类,其中包含一个方法 fourSumCount。这个方法用于解决四数之和问题:给定四个整数数组 A, B, C, 和 D,计算有多少个由一个来自 A 和一个来自 B 的数以及一个来自 C 和一个来自 D 的数构成的四元组,它们的和为 0。

逻辑分析:

  1. 初始化哈希表(Map):首先,创建一个哈希表 countAB 用于存储数组 AB 中元素两两两两数之和的频次。键为和的值,值为该和出现的次数。

  2. 计算 AB 的组合和:遍历数组 AB 中的所有元素,计算它们的和,并在哈希表 countAB 中累积这些和的计数,使用 getOrDefault 方法来简化计数累加逻辑,如果键不存在则默认值为0,然后加1。

  3. 计算四数和为0的组合数:接着,遍历数组 CD 的元素,对于每一对 uv,检查 countAB 是否包含 -u - v 这个键(即如果存在一个来自 AB 的和与 uv 之和为相反数),如果存在,则累加该和在 countAB 中的频次到答案 ans

  4. 返回结果:最后,返回累计的满足条件的四数之和为0的组合总数 ans

代码特点与优化:

  • 空间换时间:通过预计算 AB 的所有组合和及其频次,将原本需要四重循环的问题转换为两重循环加上查找,显著提高了效率。
  • 哈希表(Map)使用:利用哈希表的高效查找特性,简化了寻找特定和的操作,从原本可能的线性查找降为接近常数时间。
  • 代码简洁性:虽然逻辑清晰,但在实际应用中可能还需考虑边界条件处理(如输入数组长度为0的情况),以及优化点(如适当处理大数以避免溢出问题)。

综上所述,这段代码提供了一种有效且相对高效求解四数之和为0的组合数目的方法,体现了哈希表在优化搜索问题中的应用。

383. 赎金信

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false 。

magazine 中的每个字符只能在 ransomNote 中使用一次。

示例 1:

输入:ransomNote = “a”, magazine = “b”
输出:false
示例 2:

输入:ransomNote = “aa”, magazine = “ab”
输出:false
示例 3:

输入:ransomNote = “aa”, magazine = “aab”
输出:true

class Solution {public boolean canConstruct(String ransomNote, String magazine) {if (ransomNote.length() > magazine.length()) {return false;}int[] cnt = new int[26];for (char c : magazine.toCharArray()) {cnt[c - 'a']++;}for (char c : ransomNote.toCharArray()) {cnt[c - 'a']--;if(cnt[c - 'a'] < 0) {return false;}}return true;}
}

这段代码定义了一个名为 Solution 的类,其中包含一个方法 canConstruct。这个方法用于判断能否通过重新排列给定的杂志字符串 magazine 中的字符,来拼写出勒索要赎金信字符串 ransomNote。如果可以,则返回 true;如果不可以,则返回 false

逻辑分析:

  1. 长度检查:首先,进行一个简单的长度检查,如果赎金信的长度大于杂志字符串长度,显然无法构造,直接返回 false

  2. 字符计数数组初始化:声明一个长度为26的小写英文字母表数组 cnt,用于计数杂志字符串中每个字符出现的次数。这里利用了小写字母’a’到’z’在ASCII码表中连续的特性,减去’a’后即可映射到数组的索引。

  3. 计算杂志字符频次:遍历杂志字符串 magazine 的字符,逐个对应回字符在数组 cnt 中计数加1。利用了字符与其在ASCII码的关系,减去 ‘a’ 来索引数组位置。

  4. 检查赎金信字符可用性:接着,遍历赎金信 ransomNote 的字符,逐个检查该字符在 cnt 数组中的计数是否足够。如果有足够的字符,就将计数减1;如果不够(即计数小于0),说明该字符在杂志中数量不足,直接返回 false

  5. 返回结果:如果成功遍历完赎金信所有字符且未返回,说明可以构造出来,最后返回 true

代码特点:

  • 空间效率:使用固定大小的计数数组而非哈希表减少了空间消耗,因为只考虑了小写字母,局限了字符范围。
  • 时间效率:两重循环,时间复杂度为O(len(ransomNote) + len(magazine)),其中len表示字符串长度,因为分别遍历了两次字符串。
  • 简洁性:直接利用字符编码特性进行索引映射,减少了额外的字符判断和映射逻辑。

综上所述,此方法通过直接计数字符频次并检查是否足够来判断是否能构造赎金信,是一种直观且效率较高的实现方式。

15. 三数之和

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

class Solution {public List<List<Integer>> threeSum(int[] nums) {int n = nums.length;Arrays.sort(nums);List<List<Integer>> ans = new ArrayList<List<Integer>>();// 枚举 afor (int first = 0; first < n; ++first) {// 需要和上一次枚举的数不相同if (first > 0 && nums[first] == nums[first - 1]) {continue;}// c 对应的指针初始指向数组的最右端int third = n - 1;int target = -nums[first];// 枚举 bfor (int second = first + 1; second < n; ++second) {// 需要和上一次枚举的数不相同if (second > first + 1 && nums[second] == nums[second - 1]) {continue;}// 需要保证 b 的指针在 c 的指针的左侧while (second < third && nums[second] + nums[third] > target) {--third;}// 如果指针重合,随着 b 后续的增加// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环if (second == third) {break;}if (nums[second] + nums[third] == target) {List<Integer> list = new ArrayList<Integer>();list.add(nums[first]);list.add(nums[second]);list.add(nums[third]);ans.add(list);}}}return ans;}
}

这段代码是用于解决“三数之和”问题的Java实现,给定一个整数数组 nums,找出数组中所有和为0的三个数的组合,并返回这些组合的列表。以下是代码的逻辑解析:

  1. 初始化:

    • 首先对数组 nums 进行排序,便于后续的双指针操作。
    • 初始化一个空的结果列表 ans,用于存储满足条件的三元组。
  2. 外层循环枚举 a:

    • 用变量 first 作为外层循环变量,从0遍历到数组长度。

    • 避度处理重复值:若当前 first 不是第一个元素且与前一个元素值相同,则跳过,避免重复解。

    • 初始化 third 指针为数组最后一个元素,目标值 target-nums[first],以使 a + b + c = 0

  3. 中层循环枚举 b:

    • 用变量 second 作为中层循环变量,从 first + 1 开始遍历。
    • 处理重复值:若 second 不是 first + 1 且与前一个元素值相同,则跳过,避免重复解。
    • 维护 third 指针位置,使其满足 nums[second] + nums[third] <= target,不断向左移动直到符合条件或 second == third
    • secondthird 重合,说明后续增加的 second 不可能再满足条件,直接跳出循环。
  4. 检查并添加解:

    • nums[second] + nums[third] == target 成立时,说明找到了一个解。
    • nums[first], nums[second], nums[third] 加入临时列表 list,然后将 list 添加到结果列表 ans 中。
  5. 返回结果:

    • 遍历完成后返回结果列表 ans

这段代码通过排序和双指针技巧高效地解决了三数之和问题,时间复杂度主要受排序影响为O(nlogn),空间复杂度为O(n)(最坏情况下存储所有解)。注意,由于代码中存在若干处逻辑错误(如循环更新语句末尾的 ++ 应替换为 ;),修正后才能正常运行。

18. 四数之和

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

示例 1:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]

class Solution {public List<List<Integer>> fourSum(int[] nums, int target) {List<List<Integer>> quadruplets = new ArrayList<List<Integer>>();if (nums == null || nums.length < 4) {return quadruplets;}Arrays.sort(nums);int length = nums.length;for (int i = 0; i < length - 3; i++) {if (i > 0 && nums[i] == nums[i - 1]) {continue;}if ((long) nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {break;}if ((long) nums[i] + nums[length - 3] + nums[length - 2] + nums[length - 1] < target) {continue;}for (int j = i + 1; j < length - 2; j++) {if (j > i + 1 && nums[j] == nums[j - 1]) {continue;}if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {break;}if ((long) nums[i] + nums[j] + nums[length - 2] + nums[length - 1] < target) {continue;}int left = j + 1, right = length - 1;while (left < right) {long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];if (sum == target) {quadruplets.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));while (left < right && nums[left] == nums[left + 1]) {left++;}left++;while (left < right && nums[right] == nums[right - 1]) {right--;}right--;} else if (sum < target) {left++;} else {right--;}}}}return quadruplets;}
}

这段代码是一个Java实现,用于解决寻找数组中所有和为目标值的四数组合(4Sum)的问题。给定一个整数数组 nums 和一个目标整数 target,如果 nums 中存在四个元素 a, b, c, 和 d 使得 a + b + c + d 的和等于 target,那么找出所有这样的四元组。返回一个二维列表,其中每个列表表示一个四元组。

解析代码逻辑:

  1. 初始化: 创建一个空的 quadruplets 列表,用于存放所有满足条件的四元组。如果输入数组为空或长度小于4,直接返回空列表。

  2. 排序: 对 nums 进行排序,便于使用双指针法减少搜索空间。

  3. 三层循环:

    • 外层循环 (i): 遍历数组,避免重复,若当前数与前一个相同则跳过。
    • 中层循环 (j): 从 i+1 开始,同样避免重复,计算四个数之和的上下界,提前剪枝。
    • 双指针法 (left, right): 在 j+1length-1 之间,寻找另外两个数,使得四数之和等于 target。若找到,添加四元组到结果列表并跳过重复值,否则根据和调整指针。
  4. 返回结果: 最后返回所有满足条件的四元组列表 quadruplets

关键点:

  • 排序 是基础,使得双指针法可行。
  • 剪枝策略 减少不必要的循环,提高效率。
  • 避免重复 通过跳过相同元素,确保结果唯一性。

注意:代码中有部分地方需要修正以确保正确性,例如 quadruplets.add(Arrays.asList(...)) 应该为 quadruplets.add(Arrays.asList(nums[i], nums[j], nums[left], nums[right]))。此外,确保所有逻辑分支和边界条件正确处理。

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

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

相关文章

系统磁盘高级管理、lvm例子、创建pv、创建VG、创建lv、磁盘扩展

LVM&#xff1a; 逻辑卷&#xff0c;动态调整分区大小&#xff0c;扩展性好 创建pv pvcreate &#xff1a; 将实体 partition 创建成为 PV &#xff1b; pvscan &#xff1a; 搜寻目前系统里面任何具有 PV 的磁盘&#xff1b; pvdisplay &#xff1a; 显示出目前系统上面…

GNSS仿真测试之三种常用坐标系与转换

作者介绍 在当今的全球导航卫星系统&#xff08;GNSS&#xff09;技术领域&#xff0c;仿真测试是评估和验证GNSS接收机性能的关键环节&#xff0c;全球导航卫星系统&#xff08;GNSS&#xff09;仿真测试是确保GNSS接收机和导航解决方案在实际部署前能够正确、可靠地工作的关键…

【git】学习记录: 贮藏功能

Git 贮藏修改是一种临时存储工作目录中已经修改但尚未提交的更改的机制。通过贮藏修改&#xff0c;你可以将当前的工作目录状态保存起来&#xff0c;以便你可以在之后的时间点重新应用这些更改&#xff0c;或者在不同的分支间切换时避免冲突。 要使用 Git 贮藏修改&#xff0c…

Linux(centos)常用命令

Linux&#xff08;Centos&#xff09;常用命令使用说明文档 切换到/home目录下 使用cd命令切换目录&#xff0c;例如&#xff1a; cd /home列出/home目录下的所有文件 使用ls命令列出目录下的文件和子目录&#xff0c;例如&#xff1a; ls /home新建目录dir1 使用mkdir命…

头歌OpenGauss数据库-I.复杂查询第1关:获取前N名成绩

本关任务&#xff1a;编写函数来实现获取前N名成绩的方法。 提示&#xff1a;前面的实验没有提供编写自定义函数的示例&#xff0c;需要参考OpenGauss数据库文档学习自定义函数的使用。 score表内容如下&#xff1a; IdScore13.5223.6534.2343.8554.2363.65 --#请在BEGIN - END…

python windows 开发.exe程序笔记

import win32api import win32gui import win32con import time import tkinter as tk## pyinstaller --onefile t4.py 将python 代码打包为windows可执行文件 .exe ## airtext 大漠 def clickGoogle():hw win32gui.FindWindow("Chrome_WidgetWin_1", "新标…

解决Redis 缓存雪崩(过期时间不一致) 和 缓存穿透(黑名单)

解决Redis 缓存雪崩&#xff08;过期时间不一致&#xff09; 和 缓存穿透&#xff08;黑名单&#xff09; public Product getdetailById(Integer id) {String key "product." id;// 查询黑名单中是否有该keyBoolean b hashOperations.hasKey(PROODUCT_DETAIL_B…

算法 Hw7

Hw 7 Graph Algorithm 1 Edge detection2 Reachability3 Bitonic shortest paths 1 Edge detection 由 Cut Property 可知&#xff1a;如果 e 是从某个集合 S 到补集 V−S 的开销最小的边&#xff0c;则 e 一定所有最小生成树中。 由 Cycle Property 可知&#xff1a;如果 e 是…

Gradle常见问题及总结

使用android studio开发项目&#xff0c;难免遇到gradle相关的错误&#xff0c;在此总结。 gradle插件与gradle home版本关系错误 参考更新 Gradle Gradle下载太慢 Index of /gradle/ (tencent.com) 是国内下载地址,手动下载对应版本即可 缓存不刷新 问题描述 maven发布…

jenkins插件之xunit

分析测试工具执行的结果&#xff0c;并图形化&#xff0c;比如phpunit&#xff0c;phpstan,可分析junit格式的结果 安装jenkins插件 搜索xunit并安装 项目配置 配置 - Build Steps 您的项目 - 配置 - Build Steps, 新增 Run with timeout 超时时间根据实际情况配置 Build…

Day38 贪心算法part05

LC435无重叠区间(未掌握) 思路&#xff1a;先对数组进行排序&#xff0c;找到非重叠的区间的个数&#xff0c;然后区间的总数减去非重叠区间的个数即是需要移除的区间的个数与LC452用最少数量的箭引爆气球类似&#xff0c;但是不同的是[1,2]和[2,3]在此题并不是重叠区间但是在…

oracle怎么处理json格式

向数据库导入json相关jar包 loadjava -r -f -u bsuser/XXXX192.168.10.31/bsorcl json.jar 要删除的话&#xff0c;删除指定jar dropjava -u bsuser/XXXX192.168.10.31/bsorcl json.jar select * from user_java_classes 然后我们就可以取到json串中任意节点的值

Linux完整版命令大全(四)

2. linux系统设置命令 alias 功能说明&#xff1a;设置指令的别名。语  法&#xff1a;alias[别名][指令名称]补充说明&#xff1a;用户可利用alias&#xff0c;自定指令的别名。若仅输入alias&#xff0c;则可列出目前所有的别名设置。 alias的效力仅及于该次登入的操作。…

行列视(RCV)部署在互联网还是部署在企业内部?

行列视&#xff08;RCV&#xff09;的部署方式可以根据企业的具体需求和情况来灵活选择。它既可以部署在互联网上&#xff0c;也可以部署在企业内部。 对于希望实现远程访问、多地点协同工作或者与第三方服务集成等需求的企业&#xff0c;可以选择将行列视&#xff08;RCV&…

Postgresql源码(129)JIT函数中如何使用PG的类型llvmjit_types

0 总结 llvmjit_types文件分三部分 类型定义&#xff1a;llvm通过变量找到对应结构体的定义&#xff0c;在通过结构体内的偏移量宏使用成员变量。模版函数定义&#xff1a; 第一&#xff1a;AttributeTemplate被当做一个函数属性的模板&#xff08;例如nofree、nosync等clang…

SpringBoot项目中redis序列化和反序列化LocalDateTime失败

实体类中包含了LocalDateTime 类型的属性&#xff0c;把实体类数据存入Redis后变成这样&#xff1a; 此时&#xff0c;存入redis不会报错&#xff0c;但是从redis获取的时候&#xff0c;会报错&#xff1a; com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Ca…

Springboot项目打包:将依赖的jar包输出到指定目录

场景 公司要对springboot项目依赖的jar包进行升级&#xff0c;但是遇到一个问题&#xff0c;项目打包之后&#xff0c;没办法看到他里面依赖的jar包&#xff0c;版本到底是不是升上去了&#xff0c;没办法看到。 下面是项目打的jar包 我们通过反编译工具jdgui&#xff0c;来…

VUE3和VUE2

VUE3和VUE2 上一篇文章中&#xff0c;我们对VUE3进行了一个初步的认识了解&#xff0c;本篇文章我们来进一步学习一下&#xff0c;顺便看一下VUE2的写法VUE3是否能做到兼容&#x1f600;。 一、新建组件 我们在components中新建一个组件&#xff0c;名称为Peron&#xff0c;…

缓存降级

当Redis缓存出现问题或者无法正常工作时,需要有一种应对措施,避免直接访问数据库而导致整个系统瘫痪。缓存降级就是这样一种机制。 主要的缓存降级策略包括: 本地缓存降级 当Redis缓存不可用时,可以先尝试使用本地进程内缓存,如Guava Cache或Caffeine等。这样可以减少对Redis…

阴影映射(线段树)

实时阴影是电子游戏中最为重要的画面效果之一。在计算机图形学中&#xff0c;通常使用阴影映射方法来实现实时阴影。 游戏开发部正在开发一款 2D 游戏&#xff0c;同时希望能够在 2D 游戏中模仿 3D 游戏的光影效果&#xff0c;请帮帮游戏开发部&#xff01; 给定 x-y 平面上的…