[收获1]C++中循环的一种写法是for(int a : A){},其中的int可以是auto自动匹配类型。a是与A数组中的元素相同的变量,最先等于A数组的第一个元素,以此进入循环体。或者理解为从数组A中依次取出元素,赋值给a。
原题链接:leetcode454四数之和
[哈希法求解思路]
先看前两个数组nums1和nums2,将不重复的nums1中元素与nums2中元素之和,放进事先定义好的map中,此处使用unordered_map因为元素不重复。
此后再将map中的元素a+b与(0-(c+d))进行比较,相等,则表明a+b与c+d互为相反数,他们四个数的和为0。这里需要对nums3和nums4进行遍历,同时求出c,d两数之和,然后使用find()函数对map中的元素进行寻访,具体代码实现如下
class Solution {
public:
int fourSumCount(vector& nums1, vector& nums2, vector& nums3, vector& nums4) {
unordered_mapumap;
for(auto a : nums1){
for(auto b : nums2){
umap[a+b]++;
}
}
int count = 0;
for(auto c : nums3){
for(auto d : nums4){
if(umap.find(0 - (c + d)) != umap.end()){
count += umap[0 - (c + d)];
}
}
}
return count;
}
};
原题链接:leetcode383赎金信
第一遍做的时候,发现基础问题还是很多,比如不知道怎么给字符串通过键盘直接赋值的语句怎么写,对C++的使用有些不熟练。还是考虑用昨天学的哈希表,用大小为26的数组来统计每个字符出现的频次,先遍历第一个字符串,遇到那个小写字母,就通过ASCII码进行转换,找到count计数数组的下标,将索引对应的元素+1,然后遍历第二个字符串,找到计数数组的下标,将对应的元素-1,最后遍历输入的字符串,循环检索每一个该字符串的每一个字符,在count中找到位置,判断是不是0,不管大于还是小于0,都说明他们在两个字符串里数量上不能一一对应起来,都不符合题意,返回false.
求解源代码如下:
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int count[26]={0};
for(int i = 0;i
原题链接:leetcode15三数之和
首先想到的当然是三重循环,遍历求解,不过感觉就很……所以不用这个。
[哈希法求解]
定义一个result用来存放三元组,vector
对给定的数组进行排序 ,sort(nums.begin(),nums.end());
用双重循环对三元数组中的前两个数进行求和与去重,然后参考前面一道题的方式,int c = 0 - (nums[i] + nums[j] )与第三个数比较,如果相等就表明两数之和与第三个数互为相反数,其和为0,不能忽略对第三个数进行去重,这里可以用erase()函数。
class Solution {
public:
vector> threeSum(vector& nums) {
vector>result;
sort(nums.begin(),nums.end());
for(int i = 0;i < nums.size();i++)
{
if(nums[i] > 0){
break;
}
if(i>0&&nums[i] == nums[i - 1]){
continue;
}
unordered_setset;
for(int j = i + 1; j < nums.size();j++){
if(j > i + 2 && nums[j] == nums[j-1] && nums[j-1] == nums[j-2]){
continue;
}
int c = 0 - (nums[i] + nums[j]);
if(set.find(c) != set.end()){
result.push_back({nums[i],nums[j],c});
set.erase(c);
}else{
set.insert(nums[j]);
}
}
}
return result;
}
};
超时了……
[双指针法求解]
求解源代码如下:
class Solution {
public:
vector> threeSum(vector& nums) {
vector>result;
sort(nums.begin(),nums.end());
for(int i = 0; i < nums.size(); i++)//找到第一元素
{
if(nums[i] > 0){ //第一个元素大于0就直接返回,因为此时已经排完序了,一定要有小于0的元素,排序后,默认是升序,第一个元素为正数,一定构不成满足题意的三元组
return result;
}
if(i > 0 && nums[i] == nums[i - 1]){
continue;
}
int left = i + 1;//定义左右指针
int right = nums.size()-1;
while(right > left) //左指针一定位于右指针,再进行下列操作
{
if(nums[right]+nums[left]+nums[i]>0)right--;//三数之和大于0,要想缩小这个和,就让右指针左移
else if(nums[i] + nums[left] + nums[right] < 0)left++;//三数之和小于0,要想增大这个和,就让左指针右移,left++
else{
result.push_back(vector{nums[i],nums[left],nums[right]});//如果等于0,就放进result中
while(right > left && nums[right] == nums[right - 1])right--;//去重,针对每一次的right只需要考虑它当前的前一个数是否与其相等就可以,因为指针式不断移动的,不需要考虑和它距离超过1的元素的大小是否相等,这个问题。
while(right>left && nums[left] == nums[left + 1])left++;
right--;//两个指针向区间收缩的方向移动
left++;
}
}
}
return result;
}
};
一开始对去重很迷惑,看不太懂,看了视频才了解了。
第一个数是在遍历中定位的,如果重复了直接跳过去就好。if( i > 0 && nums[i] == nums[i -1] ){continue;}三元组内部的元素可以是像-1+(-1)+2这种,可以重复,但是两个元组之间不能重复。
后两个数的去重应该安排在找到三元组之后,然后对左右指针进行移动right--;left++;
原题链接:leetcode18四数之和
暴力的话,需要四重循环,所以还是换一种方法的好。
参考前一题目,使用双指针求解,先进行双层循环求nums[k]+nums[i],循环内使用left和right指针,找出满足nums[k]+nums[i]+nums[left]+nums[right]=target的四个数,将其作为一个四元组记录进result.
class Solution {
public:
vector> fourSum(vector& nums, int target) {
vector>result;
sort(nums.begin(),nums.end());
for(int k = 0;k < nums.size(); k++){
if(nums[k] > target && (nums[k] >= 0 || target >= 0)){
break;//如果排序后的第一个数是大于目标值target的,同时这第一个数和目标值target中有一个是正数,就可以不再继续了。因为我们要找的是第一个+后三个的和等于target,第一个超了,后面就不用看了。
}
//第一个数去重
if(k>0 && nums[k] == nums[k-1]){
continue;//这个数不能与它前一个数相等
}
for(int i = k+1; i< nums.size();i++){//第二个数的定位,从第一个数后面一个开始
if(nums[k] + nums[i] > target && (nums[k] + nums[i] >= 0 || target >= 0)){
break;//同上一级循环
}
if(i > k + 1 && nums[i] == nums[i - 1]){
continue;//对第二个数去重
}
int left=i+1;
int right = nums.size()-1;
while(right > left){
if(nums[k] + nums[i] > target -( nums[left] + nums[right])){
right--;
while(left{nums[k],nums[i],nums[left],nums[right]});
while(right > left && nums[right] == nums[right - 1])right--;//后两个数去重
while(right > left && nums[left] == nums[left + 1])left++;
right--;
left++;
}
}
}
}
return result;
}
};