牛课网数组问题总结

/*************************************************************
*给定一个数组全为正数
*求相加和为k的最大子序列的长度
*O(N)时间O(1)空间
*采用滑动窗口的思想,left为当前左边界,right为有边界,组成的窗口为
*要求的sum,判断其和要求的k之间的关系,进行指针的变化
*****************************************************/

#include<iostream>
#include<vector>
#include<algorithm>
#include<unordered_map>
using namespace std;
int getMaxLength(vector<int> &nums,int k) {
    int len = nums.size();
    if (len==0||k <= 0) return 0;   //边界检查
    int left = 0, right = 0, maxLen = 0;   //得到的最大子数组长度
    int sum = nums[0];
    while (right < len) {
        if (sum == k) {
            maxLen = max(right - left + 1, maxLen);
            sum -= nums[left++];     //因为数组全为正数,因此当找到后,让left+1位
        }
        else if (sum < k) {
            right++;
            if (right == len) break;
            sum += nums[right];
        }
        else
            sum -= nums[left++];   //left往右移动
    }
    return maxLen;
}
int main()
{
    vector<int> v = { 2,3,4,1,4,6,8,1,2,4,2 };
    cout << getMaxLength(v, 9) << endl;  //应该输出4   1,2,4,2
}

上一题的变形

/*************************************************************************************************************
*给定一个无序数组arr,其中元素可正、可负、可0,再给定一个整数k,
*求arr所有的子数组中累加和为k的最长子数组长度。
*分析:无序数组,arr,可正可负可0,求最大累加和为k的子数组的长度
*时间复杂度O(N),需要一个hash_map结构,空间复杂度为O(N)
****************************************************************************************************************/

int getMaxLength1(vector<int> &nums, int k) {
    int len = nums.size();
    if (len == 0) return 0;
    unordered_map<int, int> m; //<key,value>=<累加和,最早出现的位置>
    m[0] = -1;       // 预处理,0最早出现在-1位置
    int maxLen = 0,sum=0;
    for (int i = 0; i < len; i++) {
        sum += nums[i];   //累加和[0.。。i]
        if (m.find(sum - k) != m.end())
            maxLen = max(maxLen, i - m[sum - k]);
        if (m.find(sum)==m.end())   //注意了,如果没有出现和为sum则,将其加入哈希表中
            m[sum] = i;
    }
    return maxLen;
}
//测试
int main()
{
    vector<int> v = { 1,2,3,-2,2,5,6,-3,-3 };
    vector<int> v1 = { 5,1,2,3,5 };
    cout << getMaxLength1(v1, 5) << endl;  //应该输出4   1,2,4,2
}

变形一:

/***************************************


给定一个无序数组arr,其中元素可正、可负、可0,求arr所有的子数组中正数与负数个数相等的最长子数组长度。
分析:问题等价于将正数变为1,负数变为-1,然后就是求取最大累加和等于0的子数组的长度
************************************************************************************************/

int maxLen(vector<int> & nums) {
    for (int i = 0; i < nums.size(); i++) {
        if (nums[i] < 0) nums[i] = -1;
        else if (nums[i] > 0) nums[i] = 1;
    }
    return getMaxLength1(nums,0);  //调用上一个的函数即可。

}
int main()
{
    vector<int> v = { 1,2,3,-2,2,5,6,-3,-3 };
    vector<int> v1 = { 5,1,2,3,5 };
    cout << maxLen(v) << endl;   //6
    cout << maxLen(v1) << endl;  //0
}

变形二:
/************************************************
给定一个无序数组arr,其中元素只是1或0,求arr所有的子数组中0和1个数相等的最长子数组长度
********************************************************************/

int maxLen(vector<int> & nums) {
    for (int i = 0; i < nums.size(); i++)
        if (nums[i]== 0) nums[i] = -1;  
    return getMaxLength1(nums,0);
}
int main()
{
    vector<int> v = { 1,1,0,0,1,0,0 };
    cout << maxLen(v) << endl;  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值