4个整数数组nums1, nums2, nums3, nums4的长度均为n,有多少个元组(i,j,k,l)使得
nums[i]+nums[j]+nums[k]+nums[l]==0 (本题不包含去重的逻辑,i,j,k,l 可以相等,一组元素与一组元素之间的各个元素也可以相等)
class Solution {
public:
int fourSumCount(vector& nums1, vector& nums2, vector& nums3, vector& nums4) {
int count = 0;
for(int i=0;i
会报如下超时错误
数组的数值较大且较为分散,所以数组可以排除
将4个元素分组,分成两组(这样的时间复杂度最低O(n^2))nums1与nums2 nums3与nums4
看其中一组的元素和是否出现过,还要知道出现过的次数(value),因此使用map
unordered_map的读写效率最高
① 遍历nums1和nums2,求解nums1[i]+nums2[j]的和,将这个和及其出现的次数放到map中
② 遍历nums3和nums4,在map中查询0-(nums3[k]+nums4[l]),
如果存在key==0-(nums3[k]+nums4[l]) 就将count加上key对应的value,这点很重要,一定要加value,因为这个key可能在nums1和nums中出现多种组合,这都是满足题目要求的!!!
例如:
nums1[1]+nums1[2]=5
nums1[1]+nums1[4]=5
nums1[3]+nums2[5]=5
nums3[1]+nums4[1]=-5
这种就是nums1[i]+nums2[j]在map中存在多种组合,key==5时,对应的value==3
因此,count=count+3
代码
class Solution {
public:
int fourSumCount(vector& nums1, vector& nums2, vector& nums3, vector& nums4) {
unordered_map map;//定义map,存放nums1[i]+nums2[j]
int count = 0;
for(int i=0;i
代码
class Solution {
public:
int fourSumCount(vector& nums1, vector& nums2, vector& nums3, vector& nums4) {
unordered_map map;
int count = 0;
for(int a:nums1){
for(int b:nums2){
map[a+b]++;
}
}
for(int c:nums3){
for(int d:nums4){
if(map.find(0-(c+d))!=map.end()){
count += map[0-(c+d)];
}
}
}
return count;
}
};
以上解法和有效字母异位词比较相像,都是先遍历数组,对哈希表进行插入操作;再遍历另外的数组,在哈希表中进行查询操作
判断ransomNote字符串能否由magazine字符串中的字符组成,二者均由小写英文字母构成,但是magzine中的每个字符只能使用1次,这两点很关键
即判断ransomNote字符串中的字符是否在magazine中出现过,因此使用哈希表
由于两个字符串中的元素只包含小写字母,是连续的,是有限值且有有限个,因此想到使用数组
① 一定要先遍历magazine字符串(因为是在magazine字符串中查找ransomNote中的字符是否存在),统计magazine字符串中每个字符出现的次数(每个字符只能使用1次),记录在hash数组中;
② 再遍历ransomNote字符串,在上述统计的次数的基础上,遇到相同的字符,在hash数组中对应元素做减减的操作;
③ 最后遍历hash数组,看是否有小于0的元素,若出现小于0的元素,证明ransoNote字符串中的对应该字符数量多于magazine字符串中该字符的数量,说明ransomNote字符串不能由magazine字符串中的字符组成
代码
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int hash[26] = {0};
for(int i=0;i
代码也可以这样写,hash减减后,直接判断hash中该元素是否小于0,若小于0的话,直接return false即可,就不用后面的hash元素再继续减减操作了
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int hash[26] = {0};
for(int i=0;i
如果遇到magazine[i]==ransomNote[i],就将ransomNote中的该字符删掉,同时一定要使用break跳出这个内部for循环,因为magazine中的一个字符只能匹配ransomNote中的1个字符,如果匹配上了,那么这个字符就废了,不能再重复使用了,需要继续下一个magazine元素的循环
代码
!!!注意break的使用
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
for(int i=0;i
1个整数数组nums ,找出nums[i]+nums[j]+nums[k]==0的[i,j,k]的组合,其中i,j,k互不相等(意味着元素不能重复使用)一组中的nums[i],nums[j],nums[k]的组合不能和另一组中的nums[i],nums[j],nums[k]完全相同,比如:0 1 -1 和 1 0 -1这就重复了,所以需要去除一组
去重是关键
使用哈希表去重细节较多
不可以先将数组中相同的元素删除,因为可能会使得一些满足条件的组合消失,例如:2 2 -4
开始时一定要对数组进行排序
是和nums[i]一样,放在前面,还是放在while循环的最后面
这里在写代码时,产生了矛盾,当元素组合满足条件时,到底是先移动还是先去重呢?
丢掉解
重复解
想的比较单纯:遇到重复值,我跳过去,不就OK了嘛,但是事实不是这样,有可能有连续的多个重复的值,所以使用i++就产生了错误
如果不加right 代码 整数数组nums的长度为n,返回nums[a]+nums[b]+nums[c]+nums[d]==target的元组[nums[a],nums[b],nums[c],nums[d]],其中a,b,c,d互不相等(意味着元素不能重复使用),返回的元组不能重复,但元组内部的元素可以重复(因为数组nums中可能存在重复的元素) 和上题三数之和一样,同样使用双指针法解决 剪枝的时候要注意,因为target可正可负可零,所以剪枝逻辑就不能像三数之和那样,直接判断nums[i]>target就行了,若target可能为负数,若nums[i]>target,若nums[i+1]还是负数,那么nums[i]+nums[i+1] 1) 对于一级剪枝,所以一级剪枝要确定target>0&&nums[i]>target 同样地,对于二级剪枝,也要注意这些细节,二级剪枝时,将nums[i]+nums[j]视作一个整体,与target进行判断 流程 代码class Solution {
public:
vector
题目4:18 四数之和
题目链接:18 四数之和
题意
双指针法
class Solution {
public:
vector