题目:给定一个数组,数组中元素的值只能是1或者-1,求其和为0的最长连续子序列的长度;
数组为1,-1,1,-1,1,-1,1,-1,其结果为:8
数组为1,1,-1,1,1,-1,-1,其结果为:6
总体思想是先动态规划求出直至每个元素时,其之前所有元素的和,然后对于相同dp[i]值时候,则二者索引之差就是一个所求的长度,索引必须是最开头与最后出现的两个索引,这样才能保证最大的和为0的子序列长度,注意,若dp[i]=0,则其之前的所有序列满足题意,这时候也应该比较一下其长度是不是最大。
直接上代码:
#include "iostream"i #include "vector" #include "string" #include "map" using namespace std; int main() { // read funftion // int n; // cin >> n; // vector<int> nums(n); // for(int i = 0; i < n;++i) // { // cin >> nums[i]; // } vector<int> nums = {1, -1, 1, -1, 1, -1, 1, -1}; int n = nums.size(); vector<int> dp(n + 1, 0);//多定义一个是为了在后面区分索引0与begin_index = 0(begin_index = mp[dp[i]]) dp[1] = nums[0]; //动态规划 dp[i]统计的是直至i索引之前的和 for(int i = 2; i != n; ++i) { dp[i] = dp[i - 1] + nums[i]; } // for(auto & i : dp) // cout << i << " "; // cout << endl; //一旦两个索引处dp值相同,说明两索引之间是和为0,注意这里的两个索引是第一次出现,最后一次出现同一个dp[i]值的两个索引 int begin_index, max = 0; map<int, int> mp;//这里用map来统计dp[i]的索引 for(int i = 1; i <= n; ++i) { begin_index = mp[dp[i]];//第一次出现dp[i],则其索引是0, if(begin_index == 0 && dp[i] != 0)//dp[i]中存储的是第一次出现的索引 , 当begin_index = 0说明之前没有存入mp,并且dp[i] != 0 一旦为dp[i]=0则可以统计赋值 mp[dp[i]] = i;//统计索引 else { if(i - begin_index > max)//max记录最大索引 max = i - begin_index; } //cout << max << " "; } cout << max << endl; return 0; }