题目1 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
示例 2:
输入:nums1 = [0], nums2 = [0], nums3 = [0], nums4 = [0]
输出:1
提示:
n == nums1.length
n == nums2.length
n == nums3.length
n == nums4.length
1 <= n <= 200
-228 <= nums1[i], nums2[i], nums3[i], nums4[i] <= 228
思路
暴力迭代会超时,其时间复杂度为\(O(n^{4})\)。另一种方法就是分而治,将四个数组分为两组,其中一组的元素和与元素和个数存储到map中,另一组用遍历方法来查找总和为零的结果。
代码
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> map1;
for(auto &num1 : nums1)
{
for(auto &num2 : nums2)
{
map1[num1 + num2]++;
}
}
int sum = 0;
for(auto &num3 : nums3)
{
for(auto &num4 : nums4)
{
auto iter = map1.find(-(num3 + num4));
if(iter != map1.end())
{
sum += iter->second;
}
}
}
return sum;
}
};
题目2 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
提示:
1 <= ransomNote.length, magazine.length <= 105
ransomNote
和magazine
由小写英文字母组成
思路
这道题只需要用个额外的数组去记录每种字符出现的次数就能做了,用int[26]就能记录所有的字母。我在处理这道题时用错了hash的类型,用成了unordered_map,这个数据结构不仅占用更多字节,并且搜索效率也不是数组的O(1)。
代码
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
unordered_map<char, int> result_map;
for(auto &c : magazine)
{
result_map[c]++;
}
for(auto &c : ransomNote)
{
unordered_map<char, int>::iterator iter
= result_map.find(c);
if(iter == result_map.end())
{
return false;
}
else
{
iter->second--;
if(iter->second < 0)
return false;
}
}
return true;
}
};
题目3 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 。
提示:
3 <= nums.length <= 3000
-105 <= nums[i] <= 105
思路
这道题可以用哈希表法或者双指针法(哈希表法已超时),因为题目要求三数之和,因此可以通过一个循环来模拟一个数,循环里使用双指针来模拟另外两个数,通过多次计算将目标vector对象放入到vector<vector<int>>result中。有一点要注意的是不可重复!
代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> result;
for(int i = 0; i < nums.size() - 2; i++)
{
if(nums[i] > 0)
break;
if(i > 0 && nums[i] == nums[i - 1])
continue;
int lft = i + 1,
rht = nums.size() - 1;
while(lft < rht)
{
if(nums[i] + nums[lft] + nums[rht] == 0)
{
result.push_back(vector<int>{nums[i], nums[lft], nums[rht]});
//去重
while(lft < rht && nums[lft + 1] == nums[lft]) lft++;
while(lft < rht && nums[rht - 1] == nums[rht]) rht--;
lft++;
rht--;
}
else if(nums[i] + nums[lft] + nums[rht] < 0)
{
lft++;
}
else
{
rht--;
}
}
}
return result;
}
};
题目4 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]]
提示:
1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109
思路
这道题依旧是用双指针法,并且要注意剪枝以及题目给出的提示\(-10^{9}<=nums[i]<=10^{9}\),题目中给出的代码里用的元素类型为int,int的正整数和负数的范围为\(10^{9} < (2^{32}>>1=2,147,483,648≈2*10^{9}) < 3*10^9\),这也就表明在最后进行和运算时要进行数据类型的提升或者用更大字节的类型。
代码
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
if(nums.size() < 4)
return vector<vector<int>>();
sort(nums.begin(), nums.end());
vector<vector<int>> result;
for(int i = 0; i < nums.size() - 3; i++)
{
if(nums[i] > target && nums[i] >= 0)
break;
if(i > 0 && nums[i - 1] == nums[i])
continue;
for(int j = i + 1; j < nums.size() - 2; j++)
{
if(nums[i] + nums[j] >= 0 && nums[i] + nums[j] > target)
break;
if(j > i + 1 && nums[j - 1] == nums[j])
continue;
int lft = j + 1, rht = nums.size() - 1;
while(lft < rht)
{
if((long)nums[i] + nums[j] + nums[lft] + nums[rht] == target)
{
result.push_back(vector<int>{nums[i], nums[j], nums[lft], nums[rht]});
while(lft < rht && nums[rht] == nums[rht-1]) rht--;
while(lft < rht && nums[lft] == nums[lft+1]) lft++;
lft++;
rht--;
}
else if((long)nums[i] + nums[j] + nums[lft] + nums[rht] < target)
{
lft++;
}
else
{
rht--;
}
}
}
}
return result;
}
};
标签:nums,++,day4,随想录,rht,lft,vector,result,哈希
From: https://www.cnblogs.com/code4log/p/18391885