牛课网数组问题总结

来源:互联网 发布:球球代点刷棒棒源码 编辑:程序博客网 时间:2024/05/20 12:22

/*************************************************************
*给定一个数组全为正数
*求相加和为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
原创粉丝点击