和为0的连续最长子序列-动态规划

 
 

题目:给定一个数组,数组中元素的值只能是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;
}

猜你喜欢

转载自blog.csdn.net/u012426298/article/details/80173033