代码随想录算法训练营第七天|454.四数相加II,383. 赎金信,15. 三数之和,18. 四数之和
1.代码随想录算法训练营第一天 | 数组理论基础,704. 二分查找,27. 移除元素2.代码随想录算法训练营第二天 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II3.代码随想录算法训练营第三天 | 链表理论基础,203.移除链表元素,707.设计链表,206.反转链表4.代码随想录算法训练营第四天 | 24. 两两交换链表中的节点,19.删除链表的倒数第N个节点,面试题 02.07. 链表相交,142.环形链表II5.代码随想录算法训练营第五天 | 复习和总结6.代码随想录算法训练营第六天|哈希表理论基础,242.有效的字母异位词,349. 两个数组的交集,202. 快乐数,1.两数之和
7.代码随想录算法训练营第七天|454.四数相加II,383. 赎金信,15. 三数之和,18. 四数之和
8.代码随想录算法训练营第八天 | 344.反转字符串,541.反转字符串II,卡码网:54.替换数字,151.翻转字符串里的单词,卡码网:55.右旋转字符串9.代码随想录算法训练营第十天 | 栈与队列理论基础,232.用栈实现队列,225.用队列实现栈10.代码随想录算法训练营第十一天|20. 有效的括号,1047. 删除字符串中的所有相邻重复项,150. 逆波兰表达式求值11.代码随想录算法训练营第十三天 | 239. 滑动窗口最大值,347.前 K 个高频元素12.代码随想录算法训练营第十四天 | 二叉树理论基础,递归遍历,分别迭代遍历, 统一迭代遍历13.代码随想录算法训练营第十五天 | 层序遍历 ,226.翻转二叉树,101.对称二叉树14.代码随想录算法训练营第十六天 |104.二叉树的最大深度,559.n叉树的最大深度,111.二叉树的最小深度,222.完全二叉树的节点个数15.代码随想录算法训练营第十八天 | 513.找树左下角的值,112. 路径总和,113.路径总和ii,106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树16.代码随想录算法训练营第二十天|654.最大二叉树,617.合并二叉树,700.二叉搜索树中的搜索,98.验证二叉搜索树17.代码随想录算法训练营第二十一天|530.二叉搜索树的最小绝对差,501.二叉搜索树中的众数,236. 二叉树的最近公共祖先18.代码随想录算法训练营第二十二天 | 235. 二叉搜索树的最近公共祖先,701.二叉搜索树中的插入操作,450.删除二叉搜索树中的节点19.代码随想录算法训练营第二十三天 | 669. 修剪二叉搜索树,108.将有 序数组转换为二叉搜索树,538.把二叉搜索树转换为累加树20.代码随想录算法训练营第二十四天 | 回溯算法理论基础,77. 组合21.代码随想录算法训练营第二十五天 | 216.组合总和III,17.电话号码的字母组合22.代码随想录算法训练营第二十七天 | 39. 组合总和,40.组合总和II,131.分割回文串一、454.四数相加II
题目链接:
学习前:
思路:
-
首先定义两个HashMap对象record12和record34,对应的key存放两个数组元素的和,value存放计算的和出现的次数
-
接着遍历record12,若record存在与之和为0的元素,则计算两个value相乘的结果,并进行累积,作为输出的结果
时间复杂度:O(n^2)
空间复杂度:O(n^2)
学习后:
可以只定义一个HashMap对象,整体遍历两次,将后两个遍历一次性完成,降低时间复杂度
二、383. 赎金信
题目链接:
学习前:
思路:
- 与"LeetCode242.有效的字母异位词"的思路一致,定义一个长度为26的int数组,每个下表对应每个小写字符,值为小写字符出现的次数
- 对于ransom进行自增运算,对于magazine进行自减运算,最后对record进行判断,若所有的值均飞正,则返回true,反之false
时间复杂度:O(n+m)
空间复杂度:O(1)
学习后:
增加了对ransom和magazine长度的判断,一方面进行了优化,一方面更加严谨
三、15. 三数之和
题目链接:
学习前:
思路: 无
学习后:
思路:
-
首先对数组按照由小到大进行排序
-
3个数分别为nums[i]、nums[left]、nums[right],选定nums[i],对left和right进行移动,使得三数之和为0,并且保证三个数各不相同
for (int i = 0; i < len - 2; i++) { if (nums[i] > 0) break; if (i > 0 && nums[i] == nums[i - 1]) continue; int left = i + 1; int right = len - 1; while (left < right) { int sum = nums[i] + nums[left] + nums[right]; if (sum < 0) left++; else if (sum > 0) right--; else { List<Integer> list = new ArrayList<>(); list.add(nums[i]); list.add(nums[left]); list.add(nums[right]); res.add(list); left++; right--; while (left < right && nums[left] == nums[left - 1]) left++; while (left < right && nums[right] == nums[right + 1]) right--; } } }
时间复杂度:O(n^2)
空间复杂度:O(1)
四、18. 四数之和
题目链接:
学习前:
思路:
-
首先对数组按照由小到大进行排序
-
4个数分别为nums[a]、nums[b]、nums[c]、nums[d],依次选定nums[a]、nums[b],对c和d进行移动,使得四数之和为target,并且保证四个数各不相同
for (int a = 0; a < len - 3; a++) {
if ( nums[a]>0 && nums[a]>target) break;
if (a > 0 && nums[a] == nums[a - 1]) continue;
for(int b = a+1; b < len - 2; b++) {
if (nums[a]+nums[b]>0 && nums[a]+nums[b]>target) break;
if (b > a+1 && nums[b] == nums[b - 1]) continue;
int c = b + 1;
int d = len - 1;
while (c < d) {
long sum = nums[a] + nums[b] + nums[c]+nums[d];
if (sum < target) c++;
else if (sum > target) d--;
else {
List<Integer> list = new ArrayList<>();
list.add(nums[a]);
list.add(nums[b]);
list.add(nums[c]);
list.add(nums[d]);
res.add(list);
while (c < d && nums[c] == nums[c + 1]) c++;
while (c < d && nums[d] == nums[d - 1]) d--;
c++;
d--;
}
}
}
}
- 需要注意sum的溢出问题
时间复杂度:O(n^3)
空间复杂度:O(1)
学习后:
加深理解
五、学习总结
- 时间:3h
- 双指针的应用
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?