【题目来自灰灰考研】
2016清华大学912
求一个数组A中连续相同数字的和等于s的最长子数组长度.
例如A={1,1,2,1,1,1,2,1}, s=3.则所求子数组长度为 3
要求算法时间复杂度不超过 O(n),空间复杂度不超过 O(1) .
a) 描述算法思想
b) 伪代码实现
c) 计算程序的算法复杂度。
循环遍历数组,每当遇到一个数字时,做如下判断
- 如果当前数字不能被目标值整除,那么他肯定不能组合成目标值,直接pass掉,下一轮循环
- 如果当前数字可以被目标值整除,那么算出商,也就是如果用当前数字构成目标值的话需要多少个
- 判断这个值当前位置和所需要位数的和与数组长度的大小关系:比如说当前数字为2在数组的最后一个位置,目标值为8,如果我想用2构成8那么还需要3个,但是我已经是数组最后一个了,后面不可能有了,这种情况也要pass掉
- 如果这个位置和需要的位数也符合要求,那么就是要判断这么多位数是不是连续着都是当前值,比如当前为2,目标为8,那么后面的3个数字也都要是2
- 如果满足上述要求,那么这个数字可以构成目标值,接下来就是更新最优解了
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
int getLongSubArrayLength(int data[], int n, int target)
{
/*
代码虽然有两层循环,但是所遍历的数据元素不会重复,所以时间复杂度O(n)
*/
int num, length = 0, i, j;
for(i = 0; i < n; i++)
{
// 如果给出的数字不能整除当前数字,那么多个连续的这个数字肯定不能 构成需要的数字
if(target % data[i] != 0)
continue;
// 算出如果使用当前数字来组成目标,则需要多少个
num = target / data[i];
// 如果需要的位数和当前位置相加大于数组长度,则这个数字也不可能构成目标
if((i + num) > n)
continue;
// 如果满足可以使用当前数字构成目标的条件了,那么就要判断当前数字的后面是不是有我们需要的那么多位连续了
for(j = i + 1; j < i + num; j++)
{
if(data[j] != data[i])
{
i = j - 1;
break;
}
}
// 如果上述循环执行完毕,那么就是满足条件了
if(j == i + num)
// 更新最长长度
if(num > length)
length = num;
}
return length;
}
int main()
{
// int data[] = {1,1,2,1,1,1,2,1};
// int data[] = {1,3,4,5,1,3,2,1};
// int data[] = {1};
int result = getLongSubArrayLength(data, 1, 1);
cout<<"The Result is :"<<result<<endl;
return 0;
}
test1:
A={1,1,2,1,1,1,2,1}
s=3
结果 3
test2:
A={1,3,4,5,1,3,2,1}
s=6
结果 0
test3:
A={1}
s=1
结果 1