题目
给定一个无序数组 arr,其中元素可正、可负、可 0。给定一个整数 k,求 arr 所有的子数组中累加和为 k 的最长子数组长度。
补充问题 1:给定一个无序数组 arr,其中元素可正、可负、可 0。求 arr 所有的子数组中正数与负数个数相等的最长子数组长度。
补充问题 2:给定一个无序数组 arr,其中元素只是 1 或 0。求 arr 所有的子数组中 0 和 1 个数相等的最长子数组长度。
解答
这题的主要思想是利用了这样一个数据 s(i)),其中,i 表示数组的索引,s(i) 表示从数组开头累加到 i 索引处的累加值。
其次,使用了哈希表这一数据结构,我们用 map 来表示,map 里存储的就是存储第一次出现的 s(i) 以及 i。这里要注意的一点就是 map 中键为 0 的键值对中存储的值是 -1,表示起始时 s(i) 为 0。
代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 
 | public int getMaxLength(int[] arr, int k) {
 if (arr == null || arr.length == 0) {
 return 0;
 }
 
 HashMap<Integer, Integer> map = new HashMap<>();
 map.put(0, -1);
 int len = 0;
 int sum = 0;
 for (int i = 0; i < arr.length; i++) {
 sum += arr[i];
 
 if (map.containsKey(sum - k)) {
 len = Math.max(i - map.get(sum - k), len);
 }
 
 
 if (!map.containsKey(sum)) {
 map.put(sum, i);
 }
 }
 return len;
 }
 
 public int getMaxLength_2(int[] arr) {
 for (int i = 0; i < arr.length; i++) {
 if (arr[0] == 0) {
 continue;
 }
 arr[i] = arr[i] < 0 ? -1 : 1;
 }
 return getMaxLength(arr, 0);
 }
 
 public int getMaxLength_3(int[] arr) {
 for (int i = 0; i < arr.length; i++) {
 arr[i] = arr[i] == 0 ? -1 : 1;
 }
 return getMaxLength(arr, 0);
 }
 
 | 
测试
| 12
 3
 4
 5
 6
 
 | public static void main(String[] args) {int[] arr = {1, 2, 3, 1, 1, 1, 1, 2, 3};
 
 GetMaxLength_10 gml = new GetMaxLength_10();
 System.out.println(gml.getMaxLength(arr, 6));
 }
 
 | 
输出
5