这次的代码是提高篇
454 两数之和2
关键点1:题目要求有多少个满足和为0的元组,这里key和val都要记录,所以采用unordered_map。key为数值,val为出现的次数。
关键点2:四数相加为0,可以两两和分为两组。遍历数组1和2的和,两层for循环。若map中没有该和,插入,val为1;若map中已经存在,将其val加1,iter->second++;迭代器定义为:auto iter;
关键点3:返回值为满足条件的元组个数,为int类型。同样,遍历数组c和d的和,将其带入map中寻找。使用.find()方法,找到即autao iter = map.find(sumb) != map.end(),这里的找到是通过迭代器定义,将int 类型的result++;
383、赎金信
关键点1:这题和242思路一样。只要记得定义并初始化数组的方式:int record[20] = {0};
15、三数之和
这道题目比较繁琐,特别是剪枝和去重逻辑
关键点1: 首先,对数组进行排序,目前排序和反转算法的使用都是方法在前,加起始和终止迭代器。ed:sort(nums.begin(),nums.end());此外,需要明确的一点是这些方法的区间原则都是左闭右开。此外,nuns.end()指向的是最后一个元素的下一个元素。
关键点2:从数组中找到三个重复的元素,三数之和为0。双指针法,遍历该数组元素,指针left从i+1开始向外遍历,指针right从nums.size()-1即右端开始向内遍历,终止条件为while(right > left)。
关键点3:首先,若nums[i] > 0,则不用往下遍历了,因为数组排序过了,直接return result;
另外,数组中可能有重复的元素,所以加剪枝:if(i > 0 && nums[i] == nums[i-1]);这里的i>0因为i=0时nums[i] == nums[i-1]越界;之所以nums[i] == nums[i-1]而不是nums[i] == nums[i+1]右边界可能越界,continue;
关键点4:当找到该元组时,需要判断right向内一位是否重复,若重复,--;同样,left若与left-1相同,left++;这里的去重和剪枝是不一样的,剪枝是当前点i和前一点对比;去重时重复点不在当前遍历的i处,而且也不用continue;
18、四数之和
这题与15题很相似
关键点1:相比15题,加了两层for循环遍历,外层i和内层k遍历,左右指针还在;
关键点2:target这里不是0了,可能为正、0、负;这里排序后还要再剪枝,if(nums[k] > target && nums[k] >= 0);在内层循环里还有二级剪枝:if(nums[k] + nums[i] > target && nums[k] + nums[i] >= 0)