对上一篇博客问题进行改进https://blog.csdn.net/qq_41864967/article/details/85084614

 

给定一个只包含0或1的数组,找出其中包含相同0的个数和1的个数的最
长子序列,输出子序列的长度, 要求在O(n)的时间复杂度内完成。
如:对于数组[0,0,1,1,0],输出结果为4。子序列[0,0,1,1] 或
[0,1,1,0] 为符合条件的最长子序列,包含了两个1和两个0,个数相同。

******************************************************************************************

思路:

将所有0变为-1   0和1数目相等 就变成了求子数组和为0的最大长度

    public static int maxLengthIn01(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] == 0) {
				arr[i] = -1;
			}
		}
		int res = maxLength(arr, 0);
		return res;

	}

	public static int maxLength(int[] arr, int aim) {
		if (arr == null || arr.length == 0) {
			return 0;
		}
		// key 某个累加和sum value 这个累加和最早出现的次数
		// 取以每个位置为结尾的等于定值的子数组的最大长度的最大值
		HashMap<Integer, Integer> map = new HashMap<>();
		map.put(0, -1); // 非常重要 意思是累加和为0 最早出现的位置为 -1 默认
		int res = 0;
		int sum = 0; // 前缀和 到i位置
		for (int i = 0; i < arr.length; i++) {
			sum += arr[i]; // arr[0..i]的和 到当前位置的累加和
			if (map.containsKey(sum - aim)) { // 能找到sum-aim出现的最早位置
				// i-map.get(sum-aim):用当前位置(和为sum)-sum-aim出现的最早位置 则剩下的和为aim
				res = Math.max(i - map.get(sum - aim), res); // 更新最大长度 i-(map.get(sum-aim)+1)+1
			}
			if (!map.containsKey(sum)) {// 只放和为sum出现的最早位置
				map.put(sum, i);
			}
		}

		return res;

	}

再次改进升级 

若此不仅只有0和1  还有其他数  求0和1数目相等的最大子数组的长度

 

依然简单 可以将0变为-1  其他数字变为0  还是成了求累加和为0的题了

public static int maxLengthIn01(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] == 0) {                    //0变为1
				arr[i] = -1;
			}else if(arr[i]!=0&&arr[i]!=1){       //其他数变为0
                arr[i] = 0;
           }
		}
		int res = maxLength(arr, 0);
		return res;
	}

	public static int maxLength(int[] arr, int aim) {
		if (arr == null || arr.length == 0) {
			return 0;
		}
		// key 某个累加和sum value 这个累加和最早出现的次数
		// 取以每个位置为结尾的等于定值的子数组的最大长度的最大值
		HashMap<Integer, Integer> map = new HashMap<>();
		map.put(0, -1); // 非常重要 意思是累加和为0 最早出现的位置为 -1 默认
		int res = 0;
		int sum = 0; // 前缀和 到i位置
		for (int i = 0; i < arr.length; i++) {
			sum += arr[i]; // arr[0..i]的和 到当前位置的累加和
			if (map.containsKey(sum - aim)) { // 能找到sum-aim出现的最早位置
				// i-map.get(sum-aim):用当前位置(和为sum)-sum-aim出现的最早位置 则剩下的和为aim
				res = Math.max(i - map.get(sum - aim), res); // 更新最大长度 i-(map.get(sum-aim)+1)+1
			}
			if (!map.containsKey(sum)) {// 只放和为sum出现的最早位置
				map.put(sum, i);
			}
		}
		return res;

	}