力扣刷题题解注意(6

力扣383赎金信

首先看到小写字母作为元素,并且是对于两个字符串比较ransomNote是否包含在magazine中,所以如果使用一个哈希表来映射是不可能的。理由是,假设我们使用flag[26]作为哈希数组,ransomNote中出现字母则flag[i]++,magazine中出现字母则flag[i]--,那么最终我们只能找flag[i]为零的情况,因为如果不为零的话就说明要么ransom有,要么magazine有,反正不是都有。

但是我们找的情况不符合题意,因为如果ransomNote="aa",magazine="aab",那么其实应该返回true,但是我们的单个哈希映射会导致flag['b'-'a']=-1。单个哈希映射当然认为这是返回false。

所以应该使用两个哈希数组,并且保证magazine的哈希数组中每个元素的值都大于等于ransomNote。

首先看大于的情况:那就是要么magazine(ba)有ransomNote(a)没有,要么就是magazine(aa)有的比ransomNote(a)多;然后看等于的情况,要么是二者都没有,要么是二者都有相同数量的字母。其实我们也要根据这个题目来拓宽我们处理哈希、字符串、数组问题的思路:我们可以使用两个哈希数组。

class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        int flag1[26]={0};#存放ransomNote哈希
        int flag2[26]={0};#存放magazine哈希
        int len1=ransomNote.length();
        int len2=magazine.length();
        for(int i=0;i<len1;++i)
        {
            int temp=ransomNote[i]-'a';
            flag1[temp]++;
        }
        for(int j=0;j<len2;++j)
        {
            int temp=magazine[j]-'a';
            flag2[temp]++;
        }
        int k;
        for(k=0;k<26;++k)
        {
            if(flag2[k]<flag1[k])#保证flag2每个元素都大于等于flag1
                break;
        }
        if(k==26)
            return true;
        else 
            return false;

    }
};

力扣15三数之和 

首先看到这道题目脑子里没有任何的思路,即使我知道这道题放到了哈希的归类里面,我绞尽脑汁也没有想出任何和哈希有关的解法。但是隐约的感觉这道题需要用双指针,双指针left和right左右移动找到结果。随后看了《代码随想录》的解析,分析如下:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;//注解1
        sort(nums.begin(),nums.end());//注解2
        for(int i=0;i<nums.size();++i)
        {
            if(nums[i]>0)//注解3
                return result;
            if(i>0&&nums[i]==nums[i-1])//注解4
                continue;
            int left=i+1;//注解5
            int right=nums.size()-1;
            while(left<right)
            {
                if((nums[i]+nums[left]+nums[right])>0)//注解6
                    right--;
                else if((nums[i]+nums[left]+nums[right])<0)//注解7
                    left++;
                else 
                {
                    result.push_back(vector<int>{nums[i],nums[left],nums[right]});//注解8
                    while(left<right&&nums[right]==nums[right-1])right--;
                    while(left<right&&nums[left]==nums[left+1])left++;//注解9
                    left++;
                    right--;
                }
            }
        }
        return result;
    }
};

1.注解1:定义的是二维容器,注意二维容器的定义,方便后面直接push_back进去找到的答案,如果使用二维数组,就要考虑下标的问题。

2.注解2:sort函数用来将nums排序,这也是注解3中后面检查nums中究竟有没有三数之和的关键,如果排序之后{1,2,3,4}第一个元素1都大于0,那么整个数组不存在三个数使和为0。

3.注解4:如果nums[i]==nums[i-1],也就是说{-1,-1,-1,1,1,2,3}中第一个-1可以用来作为三数之和中的nums[i],第二个-1用来做三数之和中的nums[left],但是当nums[i]为第二个-1的时候,就不需要继续保存-1,-1,2了,避免重复。后面注解8,注解9对于left,right也是这个道理。

力扣18四数之和

认为这个题目和三数之和是相同的思路,不过多了一重循环,也多了一种减少运行时间的方式。

vector<vector<int>> fourSum(vector<int>& nums, int target) {
        vector<vector<int>>quadruplets;
        if(nums.size()<4)//不满足题目直接返回空vector
            return quadruplets;
        sort(nums.begin(),nums.end());
        int length=nums.size();
        for(int i=0;i<length-3;++i)
        {
            if(i>0&&nums[i]==nums[i-1])//去重
                continue;
            if((long)nums[i]+nums[i+1]+nums[i+2]+nums[i+3]>target)
                break;//最初的四个都大于target,那么后面肯定不大于
            if((long)nums[i]+nums[length-3]+nums[length-2]+nums[length-1]<target)
                continue;//最后面的加上最初的都小于target那么遍历从i开始后面的也没有意义,直接增大i,增大和
                //可以看做缩短运行时间的一种操作
            for(int j=i+1;j<length-2;j++)//不同于三数之和,多了一重循环
            {
                if (j > i + 1 && nums[j] == nums[j - 1]) {//以下三种去重方式同上面的去重方式
                    continue;
                }
                if ((long) nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) {
                    break;
                }
                if ((long) nums[i] + nums[j] + nums[length - 2] + nums[length - 1] < target) {
                    continue;
                }
                int left=j+1,right=length-1;
                while(left<right)
                {
                    long sum=(long)nums[i]+nums[j]+nums[left]+nums[right];
                    if(sum==target)
                    {
                        quadruplets.push_back({nums[i],nums[j],nums[left],nums[right]});
                        while(left<right&&nums[left]==nums[left+1])
                        {
                            left++;//去重第三个
                        }
                        left++;//去重结束之后移动
                        while(left<right&&nums[right]==nums[right-1])
                        {
                            right--;
                        }
                        right--;
                    }
                    else if(sum<target)
                    {
                        left++;
                    }
                    else
                    {
                        right--;
                    }
                }
            }
        }
        return quadruplets;
    }

关于哈希表C++关联式容器的总结详见:STL详解(十)—— set、map、multiset、multimap的介绍及使用_map、set、multiset、multimap底层原理-CSDN博客

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,关于力扣刷题C++常用操作,我可以给你一些常见的操作和技巧: 1. 使用 STL 容器和算法库:STL(Standard Template Library)是 C++ 标准库中的一个重要组成部分,包含了许多常用的容器和算法。在力扣刷题中,使用 STL 可以大大提高代码的效率和可读性。例如,vector 可以用来存储动态数组,sort 可以用来排序等等。 2. 使用 auto 关键字:auto 关键字可以自动推导变量类型,可以减少代码量和提高可读性。例如,auto x = 1; 可以自动推导出 x 的类型为 int。 3. 使用 lambda 表达式:lambda 表达式是 C++11 中引入的一种匿名函数,可以方便地定义一些简单的函数对象。在力扣刷题中,使用 lambda 表达式可以简化代码,例如在 sort 函数中自定义比较函数。 4. 使用位运算:位运算是一种高效的运算方式,在力扣刷题中经常会用到。例如,左移运算符 << 可以用来计算 2 的幂次方,右移运算符 >> 可以用来除以 2 等等。 5. 使用递归:递归是一种常见的算法思想,在力扣刷题中也经常会用到。例如,二叉树的遍历、链表的反转等等。 6. 使用 STL 中的 priority_queue:priority_queue 是 STL 中的一个容器,可以用来实现堆。在力扣刷题中,使用 priority_queue 可以方便地实现一些需要维护最大值或最小值的算法。 7. 使用 STL 中的 unordered_map:unordered_map 是 STL 中的一个容器,可以用来实现哈希表。在力扣刷题中,使用 unordered_map 可以方便地实现一些需要快速查找和插入的算法。 8. 使用 STL 中的 string:string 是 STL 中的一个容器,可以用来存储字符串。在力扣刷题中,使用 string 可以方便地处理字符串相关的问题。 9. 注意边界条件:在力扣刷题中,边界条件往往是解决问题的关键。需要仔细分析题目,考虑各种边界情况,避免出现错误。 10. 注意时间复杂度:在力扣刷题中,时间复杂度往往是评判代码优劣的重要指标。需要仔细分析算法的时间复杂度,并尽可能优化代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值