问题入口
例子
input: [0,0,1,0,0,0,1,1]
expected: 6
官方例子提供很多010101这样连续的例子。根据题意,像上例这样0011连续多次也是符合题意的。
解决方法
以下对官方方法的理解。感兴趣的朋友可以直接跳转这里,看官方解决方法。
蛮力法Brute force O(n^2)
int maxLength = 0;
for(int start = 0; start < nums.size(); start++)//遍历所有可能是最大连续数组的起始点
{
int zeros=0, ones=0;
for(int end = start; end < nums.size(); end++)
{
if (nums.at(end) == 0)
{
zeros++;
}
else{
ones++;
}
if (zeros == ones)//0的数量=1的数量,查看是否是最大连续数组
{
maxLength = (maxLength < (end - start +1))? end - start + 1 : maxLength;
}
}
}
return maxLength;
p.s. 这个算法c++执行会报错Time Limit Exceeded
O(n)
//O(n)
/*
返回最长的0和1数量相等的字符(数字)个数
@param count 用于标记和访问可能的最长字符串起始点。遇到0,减1;遇到1,加1。
@param length 记录起始点的索引位置。考虑最大容量,假设数组所有数字为1,那么就需要2 * nums.size()。
不要忘了还有count=0的情况。所以是2 * nums.size() + 1
@param maxlen 记录最长字符(数字)个数
*/
int length = 2 * nums.size() + 1;
int arr[length];
for (int i = 0; i < length; i++)
{
arr[i] = -2;//有谁能教教我c++初始化所有元素为一个数字的写法?用for循环好逊啊
}
arr[nums.size()] = -1; //当count=0时,也就是count + nums.size()=nums.size()时,
//说明遍历到的0和1数量持平。此时直接返回索引+1即可
int maxlen = 0, count = 0;
for (int i = 0; i < nums.size(); i++) {
count = count + (nums[i] == 0 ? -1 : 1);
if (arr[count + nums.size()] >= -1) {
//进入该分支,说明0和1的数量持平,无论count是否为0。
//如果count不为0,说明该maxlen不是从第一个元素开始算起
maxlen = (maxlen > i - arr[count + nums.size()])? maxlen : i - arr[count + nums.size()];
} else {
arr[count + nums.size()] = i;//记录count值变化的第一个索引。比如count第一次等于1时,索引位置是i。
}
}
return maxlen;
input: [1,0,1,0,1,1,0,1]的例子
HashMap
把上面的count和起始位置记录在HashMap中。
unordered_map<int,int> Hashmap;
Hashmap.insert(make_pair(0, -1));
int maxlen = 0, count = 0;
for (int i = 1; i <= nums.size(); i++)
{
Hashmap.insert(make_pair(i, -2));
Hashmap.insert(make_pair(-i, -2));
}
for (int i = 0; i < nums.size(); i++)
{
count = (nums[i] == 0) ? count-1: count+1;
if (Hashmap[count] >= -1 )
{
maxlen = (maxlen > i - Hashmap[count])? maxlen : i - Hashmap[count];
}
else
{
Hashmap[count] = i;
}
}
return maxlen;