【算法训练营day7】LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和

LeetCode454. 四数相加II

题目链接:454. 四数相加II

初次尝试

没有思路,对于map的使用还不是非常熟练,正好借这几个题多练习一下。

看完代码随想录后的想法

四个数组两两一组,写成两个嵌套的for循环,这样可以保证时间复杂度最小,其中使用map的原因是不仅要统计前两个数组的元素和,还要统计每个和出现的次数。

class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> hashMap;
int count = 0; for (int i = 0; i < nums1.size(); i++) {
for (int j = 0; j < nums2.size(); j++) {
auto iter = hashMap.find(nums1[i] + nums2[j]);
if (iter != hashMap.end()) {
iter -> second++;
}
else {
hashMap.insert(pair<int, int>(nums1[i] + nums2[j], 1));
}
}
} for (int i = 0; i < nums3.size(); i++) {
for (int j = 0; j < nums4.size(); j++) {
auto iter = hashMap.find(0 - nums3[i] - nums4[j]);
if (iter != hashMap.end()) {
count += iter -> second;
}
}
} return count;
}
};

LeetCode383. 赎金信

题目链接:383. 赎金信

初次尝试

感觉和242. 有效的字母异位词是一个思路的题,解起来不难,一遍ac。

class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
vector<int> hashVec(26, 0);
for (int i = 0; i < magazine.size(); i++) {
hashVec[magazine[i] - 'a']++;
}
for (int i = 0; i < ransomNote.size(); i++) {
hashVec[ransomNote[i] - 'a']--;
if (hashVec[ransomNote[i] - 'a'] < 0) {
return false;
}
} return true;
}
};

看完代码随想录后的想法

思路一样。


LeetCode15. 三数之和

题目链接:15. 三数之和

初次尝试

思路比较混乱,没有想到解法。

看完代码随想录后的想法

这题应该是刷题刷到现在,思考量最大的一道题了,很容易想着想着陷入疑惑,最好边画图边想。这里按照思考顺序列举几个解题的关键点:

  1. 为什么上来要先排序?LeetCode官方题解中对此有非常清楚的解释。

    「不重复」的本质是什么?我们保持三重循环的大框架不变,只需要保证:

    第二重循环枚举到的元素不小于当前第一重循环枚举到的元素;

    第三重循环枚举到的元素不小于当前第二重循环枚举到的元素。

    也就是说,我们枚举的三元组 (a, b, c) 满足a≤b≤c,保证了只有 (a, b, c)这个顺序会被枚举到,而 (b, a, c)、(c, b, a) 等等这些不会,这样就减少了重复。要实现这一点,我们可以将数组中的元素从小到大进行排序,随后使用普通的三重循环就可以满足上面的要求。

  2. 但是仅仅排序之后就可以保证输出的三元组不重复了吗?不一定,排序过后的数组仍然可能存在连续相等的元素,这可能会导致在遍历过程中,连续几个循环a取得相同的值,导致输出重复的三元组,b和c同理,所以仍然需要对abc去重。

  3. 但是对于a和bc的去重方式又有所差别,对于b和c,我们可以在left和right指针指向的下一个元素和现在指向的元素相等的时候,直接跳过下一个元素;而对于a,我们需要考虑特殊的情况,比如遇到{0, 0, 0}或者{-1, -1, 2}这样的输入时,如果使用nums[i] == nums[i + 1]这样的判断,就会漏掉(0, 0, 0)或者(-1, -1, 2)这样的三元组,所以对于a,应该使用nums[i] == nums[i - 1]这样的判断,这样才能保证既不漏掉特殊情况,又不输出因为a重复而重复的三元组。

class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
sort(nums.begin(), nums.end()); for (int i = 0; i < nums.size(); i++) {
if (nums[i] > 0) {
return ans;
} // 对a去重
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
} int left = i + 1, right = nums.size() - 1;
while (left < right) {
if (nums[i] + nums[left] + nums[right] < 0) {
left++;
}
else if (nums[i] + nums[left] + nums[right] > 0) {
right--;
}
else {
ans.push_back(vector<int>{nums[i], nums[left], nums[right]}); // 对b和c去重
while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--; left++;
right--;
}
}
} return ans;
}
};

LeetCode18. 四数之和

题目链接:18. 四数之和

初次尝试

算是三数之和的拓展题,本质上就是在三数之和的基础上再加一层for循环,但是在实际写的过程中有几个细节需要注意。

看完代码随想录后的想法

两点细节需要注意:

  1. 剪枝处理的判断条件和三数之和不同,内外两层剪枝处理的返回语句不同。
  2. 需要在四数求和的时候将int强制转型为long int,防止溢出。
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
sort(nums.begin(), nums.end()); for (int i = 0; i < nums.size(); i++) {
// 剪枝处理
if (nums[i] > target && nums[i] >= 0) {
return ans;
} if (i > 0 && nums[i] == nums[i - 1]) {
continue;
} for (int j = i + 1; j < nums.size(); j++) {
// 2级剪枝处理
if (nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) {
break;
} if (j > i + 1 && nums[j] == nums[j - 1]) {
continue;
} int left = j + 1, right = nums.size() - 1;
while (left < right) {
// 强制转型
if ((long) nums[i] + nums[j] + nums[left] + nums[right] < target) {
left++;
}
else if ((long) nums[i] + nums[j] + nums[left] + nums[right] > target) {
right--;
}
else {
ans.push_back(vector<int>{nums[i], nums[j], nums[left], nums[right]}); while (left < right && nums[left] == nums[left + 1]) left++;
while (left < right && nums[right] == nums[right - 1]) right--; left++;
right--;
}
}
}
} return ans;
}
};

【算法训练营day7】LeetCode454. 四数相加II LeetCode383. 赎金信 LeetCode15. 三数之和 LeetCode18. 四数之和的更多相关文章

  1. 【哈希表】leetcode454——四数相加II

    编号454:四数相加II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为 ...

  2. Leetcode 454.四数相加II

    四数相加II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为了使问题简单 ...

  3. Java实现 LeetCode 454 四数相加 II

    454. 四数相加 II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为 ...

  4. 代码随想录第七天| 454.四数相加II、383. 赎金信 、15. 三数之和 、18. 四数之和

    第一题454.四数相加II 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= i, ...

  5. LeetCode 445. 两数相加 II(Add Two Numbers II)

    445. 两数相加 II 445. Add Two Numbers II 题目描述 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个 ...

  6. Java实现 LeetCode 445 两数相加 II

    445. 两数相加 II 给定两个非空链表来代表两个非负整数.数字最高位位于链表开始位置.它们的每个节点只存储单个数字.将这两数相加会返回一个新的链表. 你可以假设除了数字 0 之外,这两个数字都不会 ...

  7. LeetCode454. 四数相加 II

    题目 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 分析 关键是如何想到用 ...

  8. [Swift]LeetCode445. 两数相加 II | Add Two Numbers II

    You are given two non-empty linked lists representing two non-negative integers. The most significan ...

  9. LeetCode 445——两数相加 II

    1. 题目 2. 解答 2.1 方法一 在 LeetCode 206--反转链表 和 LeetCode 2--两数相加 的基础上,先对两个链表进行反转,然后求出和后再进行反转即可. /** * Def ...

随机推荐

  1. SpringBoot的创建和特性

    一.SpringBoot的特点 创建独立的Spring应用程序 直接嵌入Tomcat.Jetty或Undertow(无需部署WAR文件) 提供自以为是的"starter"依赖项,以 ...

  2. 微服务性能分析|Pyroscope 在 Rainbond 上的实践分享

    随着微服务体系在生产环境落地,也会伴随着一些问题出现,比如流量过大造成某个微服务应用程序的性能瓶颈.CPU利用率高.或内存泄漏等问题.要找到问题的根本原因,我们通常都会通过日志.进程再结合代码去判断根 ...

  3. 乘风破浪,遇见最佳跨平台跨终端框架.Net Core/.Net生态 - 官方扩展集锦(Microsoft.Extensions on Nuget)

    什么是Microsoft.Extensions .NET Platform Extensions是一套.Net官方的API集合,提供了一些常用的编程模式和实用工具,例如依赖项注入.日志记录.缓存.Ho ...

  4. Java核心知识体系4:AOP原理和切面应用

    1 概述 我们所说的Aop(即面向切面编程),即面向接口,也面向方法,在基于IOC的基础上实现. Aop最大的特点是对指定的方法进行拦截并增强,这种增强的方式不需要业务代码进行调整,无需侵入到业务代码 ...

  5. ASP.NET CORE在docker中的健康检查(healthcheck)

    在使用docker-compose的过程中,很多程序都提供了健康检查(healthcheck)的方法,通过健康检查,应用程序能够在确保其依赖的程序都已经启动的前提下启动,减少各种错误的发生,同时,合理 ...

  6. Java SE 16 新增特性

    Java SE 16 新增特性 作者:Grey 原文地址:Java SE 16 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  7. DIN 66025标准下G Code基础代码释义

    基础/前提 XYZ指示常规的三个轴号,PQUVW为可以增加的五个轴,ABC为可以增加的旋转轴 实例 G0 快速定位(点位运动) G1 直线运动(插补) G2 顺时针圆弧运动(插补) G3 逆时针圆弧运 ...

  8. ViewGroup事件分发源码分析

    1.AndroidStudio源码调试方式 AndroidStudio默认是支持一部分源码调试的,但是build.gradle(app) 中的sdk版本要保持一致, 最好是编译版本.运行版本以及手机的 ...

  9. ar9485 win10 笔记本电脑 无线网间歇性掉线

    问题  新安装了系统,刚开始上网正常,下载东西或者待机一段时间后掉线了. wifi都能搜到,就是连不上,重启电脑可以解决,但是每次重启很麻烦,必须找到治本的方法. 排除问题 1.手机连接没有问题,排除 ...

  10. PLSQL 与 PLPGSQL

    KingbaseES 为了更好地适应用户的oracle 应用,实现了对 plsql 的支持,用户可以根据需要使用 plsql 或 plpgsql. 以下简要介绍下二者的差异 一.格式差异 1.plpg ...