剑指 Offer II 011. 0 和 1 个数相同的子数组(525. 连续数组)
题目:
思路:
【1】原本打算用双指针做个滑动窗口的,但是发现左指针的移动判断满是不好搞
【2】但是发现好像滑动窗口有点感觉的,但是解不出来用 前缀和 + 哈希表 貌似又能解
示例说明:
//输入示例[0,0,1,0,0,0,1,1]
//一开始边构建hash , [k=0 v=-1]
//当下标为0时,输入0,表中没有则填入hash中 [k=0 v=-1],[k=-1 v=0]
//当下标为1时,输入0,表中没有则填入hash中 [k=0 v=-1],[k=-1 v=0],[k=-2 v=1]
//当下标为2时,输入1,此时count由-2回退到-1,存在则获取下标0,即0-2之间(不包括0下标),和等于0,长度为2
//当下标为3时,输入0,此时count又回到-2,存在则获取下标1,即1-3之间(不包括1下标),和等于0,长度为2
//当下标为4时,输入0,表中没有则填入hash中 [k=0 v=-1],[k=-1 v=0],[k=-2 v=1],[k=-3 v=4]
//当下标为5时,输入0,表中没有则填入hash中 [k=0 v=-1],[k=-1 v=0],[k=-2 v=1],[k=-3 v=4],[k=-4 v=5]
//当下标为6时,输入1,此时count由-4变为-3,存在则获取下标4,即4-6之间(不包括4下标),和等于0,长度为2
//当下标为7时,输入1,此时count由-3变为-2,存在则获取下标1,即1-7之间(不包括1下标),和等于0,长度为6
代码展示:
优化方面:
将map改为用int数组替代这样更节约空间,而且运算更快一些 //时间4 ms击败99.32% //内存49.3 MB击败98.15% class Solution { public int findMaxLength(int[] nums) { int n = nums.length; int[] hash = new int[(n << 1) + 1]; int sum = n; int ans = 0; for (int i = 0; i < n; i++) { sum += (nums[i] << 1) - 1; if (sum == n || hash[sum] != 0) { ans = Math.max(ans, i - hash[sum] + 1); } else { hash[sum] = i + 1; } } return ans; } }
前缀和 + 哈希表的方式:
//时间23 ms击败49.83% //内存50.5 MB击败23.83% //时间复杂度:O(n),其中 n 是数组 nums 的长度。需要遍历数组一次。 //空间复杂度:O(n),其中 n 是数组 nums 的长度。 //空间复杂度主要取决于哈希表,哈希表中存储的不同的 counter 的值不超过 n 个。 class Solution { public int findMaxLength(int[] nums) { Map<Integer, Integer> map = new HashMap<Integer, Integer>(); int res = 0, counter = 0; map.put(counter, -1); for (int i = 0; i < nums.length; i++) { if (nums[i] == 1) counter++; if (nums[i] == 0) counter--; if (map.containsKey(counter)) { int prevIndex = map.get(counter); res = Math.max(res, i - prevIndex); } else { map.put(counter, i); } } return res; } } //对应的不太了解原理的 //这里有加部分打印,可以看看hash怎么跳跃 class Solution { public int findMaxLength(int[] nums) { Map<Integer, Integer> map = new HashMap<Integer, Integer>(); int res = 0, counter = 0; map.put(counter, -1); for (int i = 0; i < nums.length; i++) { if (nums[i] == 1) counter++; if (nums[i] == 0) counter--; if (map.containsKey(counter)) { System.out.println("下标为"+i); int prevIndex = map.get(counter); System.out.println("[counter:"+counter+" value:"+prevIndex+']'); res = Math.max(res, i - prevIndex); System.out.println("结果为"+res); } else { map.put(counter, i); } map.forEach((k,v)->System.out.print("[k="+k + " v="+v+"],")); System.out.println(); } return res; } }