• leetcode 525. Contiguous Array


    Given a binary array, find the maximum length of a contiguous subarray with equal number of 0 and 1.

    Example 1:

    Input: [0,1]
    Output: 2
    Explanation: [0, 1] is the longest contiguous subarray with equal number of 0 and 1.
    

    Example 2:

    Input: [0,1,0]
    Output: 2
    Explanation: [0, 1] (or [1, 0]) is a longest contiguous subarray with equal number of 0 and 1.
    

    Note: The length of the given binary array will not exceed 50,000.

    题目大意:给定一个二值数组,返回含有相同个数的0和1的最长连续子数组的长度。

    方法一:暴力法(超时)


    C++代码

    我们考虑所有的连续子数组,判断0和1个数是否相同,如果相同,则与当前已找到的符合条件的连续子数组的长度进行比较。

     1  int findMaxLength(vector<int>& nums) {
     2         int sum = 0;
     3         int maxsize = 0;
     4         for (int i = 0; i < nums.size(); ++i) {
     5             sum = 0;
     6             for (int j = i; j < nums.size(); ++j) {
     7                 //计算[i,j]的和,[i, j]的和=[i,j-1]的和+j,所以可以利用前面得到的结果
     8                 (nums[j] == 1) ? (sum += 1) : (sum -= 1);
     9                 if (sum == 0 && (maxsize < j - i + 1)) {
    10                     maxsize = j - i + 1;
    11                 }
    12             }
    13         }
    14         return maxsize;
    15     }

    在这里,我们讨论索引[i,j]中1和0的个数是否相等时,避免直接统计1和0的个数,而是利用累加和,是1则加1,0则减1,累加和为0则代表1和0个数相同。

    时间复杂度:$O(n^2)$

    空间复杂度:$O(1)$


    方法二:哈希表

    假设S[i]表示数组索引为0到i的子数组各元素之和(遇到1则加1,遇到0则减1),如果S[i]=0,那么[0,i]组成的子数组是符合条件的;

    假如S[i] !=0 且 S[i] = m,然而存在最小的$j in [0,i)$使得S[j] = m,那么[j+1, i]是符合条件的连续子数组。因为S[i]=S[j],我们要根据累加和m,得到索引j,所以需要建立累加和映射到索引的哈希表。

    累加和的取值范围为[-n, n](n为数组的长度,-n时表示数组全为-1, n时表示数组全为1),所以开辟一个2n+1的数组。

     1 int findMaxLength(vector<int>& nums) {
     2         int len = nums.size();
     3         vector<int> index(2 * len + 1, -2); //初始化为-2表示这些累加和尚未出现
     4         index[len] = -1; //一开始累加和为0,索引为-1
     5         int maxlen = 0, sum = 0;
     6         for (int i = 0; i < nums.size(); ++i) {
     7             sum += (nums[i] == 0) ? -1 : 1;
     8             if (index[sum + len] >= -1) { //如果当前累加和已经出现过,则比较大小并更新maxlen,这里就不用更新累加和对应的索引
     9                 maxlen = max(maxlen, i - index[sum + len]);
    10             } else { //否则记录累加和对应的索引
    11                 index[sum + len] = i;
    12             }
    13         }
    14         return maxlen;
    15     }

    需要注意的是,累加和为m可能对应多个索引,因为要找最长的连续子数组,所以我们只能保存最小的索引。

    时间复杂度:$O(n)$

    空间复杂度:$O(n)$

    或者利用STL map数据结构:

     1 int findMaxLength(vector<int>& nums) {
     2         int len = nums.size();
     3         unordered_map<int, int> hM;
     4         int maxlen = 0, sum = 0;
     5         for (int i = 0; i < nums.size(); ++i) {
     6             sum += (nums[i] == 0) ? -1 : 1;
     7             if (sum == 0)
     8                 maxlen = i + 1;
     9             if (hM.find(sum + len) != hM.end()) { 
    10                 maxlen = max(maxlen, i - hM[sum + len]);
    11             } else {
    12                 hM[sum + len] = i;
    13             }
    14         }
    15         return maxlen;
    16     }

  • 相关阅读:
    【转】什么时候用抽象类,什么时候用接口
    高内聚松耦合在程序设计中如何做到
    如何做高水平的程序项目设计者
    NHibernate条件查询(Criteria Query)
    Oracle学习笔记之表结构修改
    Java集合类和HashMap遍历
    Asp.net中基于Forms验证的角色验证授权
    Springconfig.xml数据库操作Bean配置
    Java 常用排序算法实现快速排序、插入排序、选择、冒泡
    .net消息队列
  • 原文地址:https://www.cnblogs.com/qinduanyinghua/p/13040796.html
Copyright © 2020-2023  润新知