近来朋友给了一道题
给出一个数组,要求算出只含有两个两个重复数字的最长连续子数组的长度;
比如[1,2,3,4,4,5,6,6,7,7,7,8],满足这个条件的连续子数组是[6,6,7,7,7],答案为5
想了个思路,大致如下:
开始的时候子数组为空,遇到新的元素就放入,直到出现第三种数字的时候,我们可以认为现在手上就是一个只含有两种数字的连续子数组,但是不一定是最长,记下长度,然后放弃原有的、不能和现在这个数字连起来的数,继续计算。画成图就是下面这样:
final1 | final2 | | index | | | v v v +----|-----------------------|---+ ··· 0 | 1 1 1 1 2 2 2 1 2 2 2 | 3 ··· +----|-----------------------|---+ | the sub array now |
index是我们现在遇到的第三种数字,手头现在有的数字是1和2,我们可以记下现在手里这个子数组的长度,然后显然应该放弃1,留下最后的2,和3形成新的子数组。也就是下面这样
+--------------------|---------|-+ ··· 0 1 1 1 1 2 2 2 1 | 2 2 2 3 | ··· +--------------------|---------|-+ | new sub |
然后继续遍历,继续成长,这样一来,就会得到所有满足条件的子数组的长度。同时,因为只要最大值,所以可以只记录最大值。这样就只遍历一遍得到了结果,代码用来C写的。
在这里面出现了几个变量,index是我们遍历的位置,不用说肯定要用的,再用一个current length来保存目前的子数组长度,还有max length记目前为止的最大长度,index-1决定了谁留下来组成新的数组(也可以用final1和final2谁比较大来决定),final1和final2还决定了新的子数组的长度,然后还需要记一下数的类型,差不多就这些
以下是代码:
1 #include <stdio.h> 2 3 int main() { 4 // 测试样例 5 int nums[12] = {1,2,3,4,4,5,6,6,7,7,7,8}; 6 int length = 12; 7 8 int type[2] = {-1, -1}; // 记录手头有的是哪两种数字 9 int final[2] = {-1, -1}; // 两个final 10 11 int maxLgt = 0, curLgt = 0; // 当前的最大长度,和子数组成长到的最大长度 12 13 for (int index = 0; index < length; index++) { 14 15 // 首先是刚开始,这里我还没有两种数,所以来者不拒 16 if (type[0] == -1 && type[1] == -1) { curLgt++; type[0] = nums[index]; final[0] = index; } 17 else if (type[0] != -1 && type[1] == -1) { 18 curLgt++; 19 if (type[0] == nums[index]) { final[0] = index; } 20 else { type[1] = nums[index]; final[1] = index; } 21 } 22 23 // 手头现在已经有两种数 24 else { 25 // 和现有一样就放入,子数组长度+1 26 if (type[0] == nums[index]) { curLgt++; final[0] = index; } 27 else if (type[1] == nums[index]) { curLgt++; final[1] = index; } 28 // 第三种数出现了,就是前面的图里的情况 29 else { 30 // 比较只留下最大值 31 maxLgt = maxLgt > curLgt ? maxLgt : curLgt; 32 // 留下比较靠后的数字 33 if (final[0] < final[1]) { curLgt = index - final[0]; type[0] = nums[index]; final[0] = index; } 34 else { curLgt = index - final[1]; type[1] = nums[index]; final[1] = index; } 35 } 36 } 37 } 38 // 最后一个子数组,因为后面没有数了,也就没有所谓的第三种数,但是这个子数组也是要算入的 39 int most_length = maxLgt > curLgt ? maxLgt : curLgt; 40 41 // 输出结果 42 printf("%d\n", most_length); 43 return 0; 44 }