题目:

输入一个只包含0和1的数组,请问如何求0和1的个数相同的最长连续子数组的长度?例如在数组[0,1,0]中有两个子数组包含相同个数的0和1,分别是[0,1],[1,0],它们的长度都是2,因此输出2。

分析:

这道题可以用面试题10的思路,但是需要将0转换为-1,题目就变为求包含相同数目的1和-1的最长子数组长度,在一个只包含数字1和-1的数组中,如果子数组1和-1的数目相同,那么子数组的所有数字之和为0,题目就变成求数字之和为0的最长子数组的长度。

扫描时,累加已经扫描过的数字之和,如果数组中前i个数字之和为m,前j个数字之和也为m,那么从第i+1个数字到第j个数字的子数组的数字之和为0,这个和为0的子数组的长度的长度是j-i。从第一数字开始到当前扫描的数字累加之和保存到一个哈希表中,对一个哈希表的key值,由于我们为了求出数字之和为0的最长子数组的长度,因此还需要知道第1次出现累加之和为m时扫描到的数组下标对应哈希表的value值。

该算法时间复杂度为O(n),空间复杂度为O(n)。

示意图以及对应的代码:

剑指offer11:0和1个数相同的子数组_面试

package com.wzc;

import java.util.HashMap;
import java.util.Map;

public class FindMaxLength {
public static void main(String[] args) {
int[] nums = {0,1,0,1,1,0,1};
int maxLength = findMaxLength(nums);
System.out.println(maxLength);
}
public static int findMaxLength(int[] nums){
// 建立哈希表
Map<Integer,Integer> sumToIndex = new HashMap<>();
// 哈希表加入的key也就是sum是0,对应的value是-1,方便以后的i-j求长度操作
sumToIndex.put(0,-1);
int sum = 0;
int maxLength=0;
for (int i = 0; i < nums.length; i++) {
// 将数组中的0转换为-1
sum += nums[i] == 0? -1:1;
// 如果哈希表中存在sum,则求出i-j的长度并与之前的长度最大值比较,取两者中的最大值
if (sumToIndex.containsKey(sum)){
maxLength = Math.max(maxLength,i-sumToIndex.get(sum));
}else {
// 如果哈希表中不存在该sum,添加该sum以及对应的i值,对应的i值也就是j,第一次出现该sum的下标
sumToIndex.put(sum,i);
}
}
return maxLength;
}
}

剑指offer11:0和1个数相同的子数组_面试_02