【算法训练营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. CMAKE编译时如何自动下载第三方库并解压、安装到指定目录

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 导语 在日常开发过程中难免会使用到第三方库或者需要将部分库分离另外存储,如果将库与代码放在一起难免会造成工程庞大,此时就可 ...

  2. (WebFlux)002、如何打印日志与链路ID

    一.背景 最近在持续改造项目,想通过日志查看用户所有的接口链路日志.在原来基于SpirngMVC的时候,那是比较好处理的,通过ThreadLocal,放入TraceId,就可以把一个TraceId传到 ...

  3. ELK技术-IK-中文分词器

    1.背景 1.1 简介 ES默认的分词器对中文分词并不友好,所以一般会安装中文分词插件,以便能更好的支持中文分词检索. 本例参考文档:<一文教你掌握IK中文分词> 1.2 IK分词器 IK ...

  4. KingbaseES 参数 - ignore_char_null_check

    KingbaseES 基于PostgreSQL进行了大量的Oracle兼容性开发,为了能同时兼容Oracle 和 PG 的特性,增加参数进行控制.以下介绍 KingbaseES 下特有的参数 igno ...

  5. Java 多线程:锁(二)

    Java 多线程:锁(二) 作者:Grey 原文地址: 博客园:Java 多线程:锁(二) CSDN:Java 多线程:锁(二) AtomicLong VS LongAddr VS Synchroni ...

  6. Python 第四次实验

    1.(程序设计)定义函数def GetRandomChar(),返回一个随机的数字或大写或小写字母,每个符号出现的机会相等.调用该函数8次,生成并输出一个8位的验证码.用户输入该验证码,如果验证码正确 ...

  7. 关于“No loop matching the specified signature and casting was found for ufunc lstsq_n”问题的解决

    下面这段代码是使用MatPlotLib绘制数据随时间变化的趋势. import datetime as dt import numpy as np import pandas as pd import ...

  8. saas 服务多语言 SDK

    简介 saas 服务一般提供了一个文档来描述提供的 OpenAPI,然会每个用户根据文档自己实现签名.调用等功能的封装,这部分会出现各种各样的问题,因此用户更希望平台直接提供一个 SDK. darab ...

  9. 2.2 virtualenv 虚拟环境

    有的时候因为各种原因,在操作系统下,我们会安装很多版本的Python解释器.同样,我们也有可能因为各种原因,需要不同版本的模块,比如Django1.8,Django1.11.再加上pip工具管理器的版 ...

  10. Kubernetes容器运行时弃用Docker转型Containerd

    文章转载自:https://i4t.com/5435.html Kubernetes社区在2020年7月份发布的版本中已经开始了dockershim的移除计划,在1.20版本中将内置的dockersh ...