力扣 每日一题 525. 连续数组

给定一个二进制数组 nums , 找到含有相同数量的 01 的最长连续子数组,并返回该子数组的长度。数组中元素只包含0和1.


今天的是个中等题,需要点思路。

1.刚开始只想到暴力,依次计算区间内0和1的数量,计算时,只需要将区间内的数值相加,如果得到的结果是区间长度的一半,则说明此区间内的0和1数量一致,时间复杂度O(n2)。超时了。

 1  public int findMaxLength(int[] nums) {
 2         int res = 0;
 3         for(int i = 0;i<nums.length-1;i++){
 4             int total = nums[i];
 5             for(int j=i+1;j<nums.length;j++){
 6                 total+=nums[j];
 7                 if(((j-i+1)&1)!=1&&(total==Math.ceil((j-i+1)/2))){
 8                     res = Math.max(res,j-i+1);
 9                 }
10             }
11         }
12         return res;
13 
14     }

 

2.中间想到用前缀和来快速计算区间内的数值,但是时间复杂度依然是O(n2)。

3.看了提示哈希表,想想是不是有方法使用哈希表来降低前缀和的复杂度。想到如果从prefix[i]= prefix[j]+(j-i)/2的话,就说明j与i之间的数满足条件(0的数量与1的数量相等),那我们就可以使用哈希表,来遍历存储前i个前缀和,key是前缀和,value是最早的前缀和为key的index,计算到j时,判断是否存在prefix[i]-(j-i)/2的值,然后计算即可。测试时,对于数组{0,0,1,0,0,0,1,1}失败,因为prefix[0]=0,prefix[1]=0,正确答案应该是从1开始算起,这里确从0开始算起。

4.大杀招,看题解,之前方向是对了,没有找对方法,题解中将0变为-1,这样就避免了前缀和一致的问题,可以保证前缀和的不一致,这样符合条件的区间和应该为0,则判断条件变为了prefix[i]=prefix[j],更简单易懂。

 1  public int findMaxLength(int[] nums) {
 2         int res = 0;
 3         Map<Integer,Integer> map = new HashMap<>();
 4         int count = 0;
 5         map.put(0,-1);
 6         for(int i = 0;i<nums.length;i++){
 7             if(nums[i]==1){
 8                 count++;
 9             }else{
10                 count--;
11             }
12             if(map.containsKey(count)){
13                 res = Math.max(res, i-map.get(count));
14             }else{
15                 map.put(count,i);
16             }
17         }
18         return res;
19 
20     }

 

posted on 2021-06-03 11:40  jejas  阅读(58)  评论(0编辑  收藏  举报