剑指 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;
    }
}

 

posted @ 2023-03-08 10:33  忧愁的chafry  阅读(23)  评论(0编辑  收藏  举报