• 基于leetcode的算法训练:Day4


    2.6 和为k的子数组

    题目描述:给定一个整数数组和一个整数 k **,**请找到该数组中和为 k 的连续子数组的个数。

    题目链接:剑指 Offer II 010. 和为 k 的子数组 - 力扣(LeetCode)

    题目难度:✨✨✨

    超时不看的暴力WA

    也是一道暴力不可破的题目,暴力题解如下:

    class Solution {
    public:
        int subarraySum(vector<int>& nums, int k) {
            //找到和为k的连续子数组的个数
            int len=nums.size();
            vector<int>preSum(len,0);
            for(int i=0;i<len;i++){
                if(i){
                    preSum[i]=preSum[i-1]+nums[i];
                }else{
                    preSum[i]=nums[i];
                }
            }
            int ans=0;
            for(int i=0;i<len;i++){
                for(int j=i;j<len;j++){
                    if(preSum[j]-preSum[i]+nums[i]==k){
                        ans++;
                    }
                }
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    参考题解

    思路:

    • hashmap+前缀和
    • 遍历数组,求该index下的前缀和为preSum,则只需要计算index之前和为preSum-k的个数即可,用哈希表存前缀和为preSum的个数
    • 计算完上述后更新哈希表,遍历下一个index+1

    代码:

    class Solution {
    public:
        int subarraySum(vector<int>& nums, int k) {
            //找到和为k的连续子数组的个数
            int ans=0;
            int len=nums.size();
            int preSum=0;
            unordered_map<int,int>mp;
            mp[0]=1;
            for(int i=0;i<len;i++){
                preSum+=nums[i];
                int target=preSum-k;
                if(mp.find(target)!=mp.end()){
                    ans+=mp[target];
                }
                //更新hash
                if(mp.find(preSum)==mp.end()){
                    mp[preSum]=1;
                }else{
                    mp[preSum]+=1;
                }
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.7 0和1个数相同的子数组

    题目描述:给定一个二进制数组 nums , 找到含有相同数量的 01 的最长连续子数组,并返回该子数组的长度。

    题目链接剑指 Offer II 011. 0 和 1 个数相同的子数组 - 力扣(LeetCode)

    题目难度:✨✨✨

    抖机灵不看的WA案例:

    不考虑全部通过的话,其实每次考虑min(0的前缀个数,1的前缀个数)就可以覆盖掉大部分的样例

    class Solution {
    public:
        int findMaxLength(vector<int>& nums) {
            //找到具有相同数量的01最长连续子数组
            int len=nums.size();
            vector<int>count_one(len,0);
            for(int i=0;i<len;i++){
                if(i==0){
                    count_one[i]=nums[i];
                }else{
                    count_one[i]=nums[i]+count_one[i-1];
                }
            }
            int ans=0;
            for(int i=0;i<len;i++){
                int temp=min(count_one[i],i+1-count_one[i]);
                temp*=2;
                if(temp>ans){
                    //printf("i=%d,count_one=%d count_zero=%d\n",i,count_one[i],i+1-count_one[i]);
                    ans=temp;
                }
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    官方题解

    不得不说……还是很棒的题解,所以看完之后需要自己复现一下

    思路

    • 利用unordered_map存储最早出现的和为cnt的下标preIndex
    • 将原始数组中的0视作-1,将原问题转化为求和为0的最长子数组,那么前缀和相等的下标们相减得到的最长长度即为答案(说明中间部分和为0)

    代码

    class Solution {
    public:
        int findMaxLength(vector<int>& nums) {
            int len=nums.size();
            int ans=0;//最大长度
            unordered_map<int,int>mp;//存储最早的前缀和为cnt的index
            int cnt=0;
            mp[cnt]=-1;
            for(int i=0;i<len;i++){
                if(nums[i]==1){
                    cnt+=1;
                }else{
                    cnt-=1;
                }
                if(mp.find(cnt)!=mp.end()){
                    int preIndex=mp[cnt];
                    ans=max(ans,i-preIndex);
                }else{
                    mp[cnt]=i;
                }
                
            }
            return ans;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
  • 相关阅读:
    SSL OV证书和DV、EV证书的区别
    Java.lang.Class类 getDeclaredConstructors()方法有什么功能呢?
    踩点记录-_-!!!
    基于springboot在线考试报名系统毕业设计源码031706
    [附源码]计算机毕业设计JAVAjsp医药管理信息系统
    当你在Linux系统中编译安装MySQL数据库卡住了怎么办?
    html5 语义化标签实用指南
    基于Python实现类高级语言的词法分析器
    面向mMTC的5G网络多随机接入机制性能优化策略
    2022年字节跳动抖音日常实习面经
  • 原文地址:https://blog.csdn.net/qq_45751990/article/details/126808878