求只含有两种数字的最长连续子数组的长度

近来朋友给了一道题

  给出一个数组,要求算出只含有两个两个重复数字的最长连续子数组的长度;

  比如[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 }

 

转载于:https://www.cnblogs.com/guobaoxu/p/10850582.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值