【题目】
给定一个数组arr,和一个整数aim,求在arr中,累加和等于num的最长子数组的长度
例子:
arr = { 7,3,2,1,1,7,7,7 } aim = 7
其中有很多的子数组累加和等于7,但是最长的子数组是{ 3,2,1,1 },所以返回其长度4
【解题】
使用map, 从数组第一个数开始累加, 记录累加和到某个值的第一个位置
map初始存放数据为<0, -1>因为没有一个数字累加的和设置为0,该数字位置为数组的 - 1位置【即数组未开始遍历】
map<sum, index>, 当sum不变时,map不更新!!!
注意:
我们要找的是sum - aim = index == key在map中最早出现的位置,并进行记录
比如:7 3 2 1 1 7 - 6 - 1 7 num == 7
在累积第0个数字 7,sum = 7, sum - aim = 0, map中存在key = 0的位置,最早出现的 位置为 - 1,
说明能组成一个子数组,使得累加和为aim,数组长度为0 - ( - 1) = 1
然后继续向后遍历,当遍历到第4个数字1时,
map记录为{ <0,-1><7,0><10,1><12,2><13,3><14,4> },
此时sum为14, sum - aim = 14 - 7 = 7, key = 7存在map中,最早出现的位置为0,
说明能组成一个子数组,使得累加和为aim,数组长度为4 - (0) = 4
【代码】
1 #pragma once 2 #include <iostream> 3 #include <map> 4 #include <vector> 5 6 using namespace std; 7 8 int mostLongSubArray(vector<int>v, int aim) 9 { 10 int res = 0;//记录最长记录 11 map<int, int>m;//记录累加和 12 m[0] = -1;//最开始的位置sum为0 13 int sum = 0; 14 for (int i = 0; i < v.size(); ++i) 15 { 16 sum += v[i]; 17 if (m.find(sum) == m.end())//累加和不存在 18 m[sum] = i; 19 auto ptr = m.find(sum - aim); 20 if (ptr != m.end())//记录存在 21 res = res > (i - (ptr->second)) ? res : (i - (ptr->second));//更新子数组最长记录 22 } 23 return res; 24 } 25 26 void Test() 27 { 28 vector<int>v; 29 v = { 7,3,2,1,1,7,7,7 }; 30 cout << mostLongSubArray(v, 7) << endl; 31 v = { 7,3,2,1,1,7,-6,-1,7 }; 32 cout << mostLongSubArray(v, 7) << endl; 33 v = { 7,5,2,4,3,1,1,1,1,1,1,1,1,7 }; 34 cout << mostLongSubArray(v, 7) << endl; 35 }