左神算法进阶班8_1数组中累加和小于等于aim的最长子数组
【题目】
给定一个数组arr,全是正数;一个整数aim,求累加和小于等于aim的,最长子数组,要求额外空间复杂度O(1),时间复杂度O(N)
【题解】
使用窗口:
双指针,当sum <= aim,,R->, 当sum > aim, L->记录最大的R - L即可
【进阶】
给定一个数组arr,值可正,可负,可0;一个整数aim,求累加和小于等于aim的,最长子数组,要求时间复杂度O(N)
【题解】
之所以比原题更难,是因为负数可以使得整个子数组开始的和很大,但加到负数时,整体和就变小了
借助两个数组
min_sum[] //min_sum[i] == 即必须以i开头的数组的最小累积和
min_sum_index[]// min_sum_index[i] == 即以i开头数组的最小累加和的达到的最右端位置
技巧:
从数组的后向前算:
当n位置的最小累加和为负数时,那么n - 1的最小累加和一定是自己加上n的最小累加和,其最右边界与n相同
当n位置的最小累加和为正数时,那么n - 1的最小累加和一定是自己,因为再向后面加也是加一个正数,其最右边界就是自己的位置
求解:
从第0个数开始,R直接到0位置的最右边界,sum + 0位置的最小累加和,若,sum<aim, 则再加入R位置的最小累加和,并且R移到R位置的最右边界
直至sum>aim,则可以知道最长数组是多少了
【代码】
1 #pragma once 2 #include <iostream> 3 #include <vector> 4 5 using namespace std; 6 7 int theLongestArray(vector<int>v, int aim) 8 { 9 //使用两个指针,作为窗口的左右端 10 int l = -1; 11 int r = 0; 12 int sum = 0; 13 int res = 0; 14 for (; r < v.size(); ++r) 15 { 16 sum += v[r]; 17 while (sum > aim && l < r)//向右移动窗口 18 { 19 ++l; 20 sum -= v[l]; 21 } 22 res = res > (r - l) ? res : (r - l); 23 } 24 return res; 25 } 26 27 28 int theLongestArray_2(vector<int>v, int aim) 29 { 30 int* min_sum = new int[v.size()];//以i开头的数组的最小和 31 int* min_sum_index = new int[v.size()];//以i开头的数组的最小和数组右端 32 for (int i = v.size()-1; i >= 0; --i) 33 { 34 if (i + 1 < v.size() && min_sum[i + 1] < 0)//右端最小和为负数,则可加上自己比自己更小 35 { 36 min_sum[i] = min_sum[i + 1] + v[i]; 37 min_sum_index[i] = min_sum_index[i + 1]; 38 } 39 else//右端为整数,加上自己比自己大,那么就以自己为最小的数组和 40 { 41 min_sum[i] = v[i]; 42 min_sum_index[i] = i; 43 } 44 } 45 //定义窗口的左右边界 46 int l = -1; 47 int r = 0; 48 int res = 0; 49 int sum = 0; 50 for (int i=0;i<v.size();++i) 51 { 52 sum += min_sum[i]; 53 r = min_sum_index[i]; 54 while (l<r && sum>aim) 55 { 56 ++l; 57 sum -= v[l]; 58 } 59 res = res > (r - l) ? res : (r - l); 60 } 61 delete[]min_sum; 62 delete[]min_sum_index; 63 return res; 64 65 } 66 void Test() 67 { 68 vector<int>v; 69 v = {1,2,3,4,5,1,1,1,1,1,1,1,7,8,9}; 70 cout << theLongestArray(v, 7) << endl; 71 v = { 1,2,3,4,5,1,1,-99,1,1,1,1,1,7,8,9,10,11,-99}; 72 cout << theLongestArray_2(v, 7) << endl; 73 }