连续子数组的问题,本来想在原来那个写,但是怕太多了自己都不想看了,重新开一个

Leetcode525:连续数组
题目:
在这里插入图片描述
方法1:把0变-1,等价于求连续子数组累加和为0的最大连续子数组的长度,但是这种问题都会有一个边界,只要求最大连续子数组的长度都会有边界问题,这个是0,-1 但是如果我改成求累加和为7的最大连续子数组的长度,那么边界就是7,-1,也就是首先把(7,-1)放到map里面

class Solution {
    public int findMaxLength(int[] nums) {
        //
        for(int i=0;i<nums.length;i++){
            if(nums[i]==0){
                nums[i]=-1;
            }
        }
        //求累加和为0的最大子数组长度
        int cur=0;
        Map<Integer,Integer> map=new HashMap();
        map.put(0,-1);
        int max=0;
        for(int i=0;i<nums.length;i++){
            cur+=nums[i];
            if(map.containsKey(cur)){
                max=Math.max(max,i-map.get(cur));
            }else{
                map.put(cur,i);
            }
        }
        return max;
    }
}

方法2:就是用一个help数组,记录0和1的数量,每到一个新位置的时候,更新数量,同时计算差值,如果此差值在以前出现过,那么下标相减就是结果,更新max,但是注意一下边界问题,这个问题的边界依然是差值=0,的情况

class Solution {
    public int findMaxLength(int[] nums) {
        Map<Integer,Integer> map=new HashMap();
        int[] help=new int[2];
        map.put(0,-1);//同样这个方法也会 有边界问题,也就是如果差值为0,那么从头到尾就是最长
        int max=0;
        int cha=0;
        for(int i=0;i<nums.length;i++){
            int a=nums[i]==0?help[0]++:help[1]++;//这个a没用,主要是我想用三木
            cha=help[1]-help[0];
            if(map.containsKey(cha)){
                max=Math.max(max,i-map.get(cha));
            }else{
                map.put(cha,i);
            }
        }
        return max;
    }
}

leetcode 560 和为k连续子数组的数量
题目:
在这里插入图片描述
就是计算前缀和,然后看当前前缀和-k是否在以前出现过,map中放的是前缀和以及这个前缀和出现了几次,注意一个边界条件,那就是前缀和为0,默认出现1次,就是到自己算一次。

class Solution {
    public int subarraySum(int[] nums, int k) {
        Map<Integer,Integer> map=new HashMap();
        map.put(0,1);
        int res=0;
        int cur=0;
        for(int i=0;i<nums.length;i++){
            cur+=nums[i];
            if(map.containsKey(cur-k)){
                res+=map.get(cur-k);
            }
            map.put(cur,map.getOrDefault(cur,0)+1);
        }
        return res;
    }
}

leetcode1074 元素和为目标值的子矩阵数量(我终于自己做出来了,看别人的没看懂。。。菜是原罪)
题目:
在这里插入图片描述
分析:就是把矩阵信息压缩,然后变成压缩矩阵求等于k的连续子数组的数量(变成了leetcode560那个题了,我真的太聪明了),矩阵信息压缩太有用了

class Solution {
    public int numSubmatrixSumTarget(int[][] arr, int target) {
        //同样可以用个压缩矩阵,但是作用和矩阵子序列和最大那个不一样,我这个矩阵表示的是从某一行到此行的总和,然后遍历这个矩阵和target做比较
        if(arr==null||arr.length==0||arr[0].length==0){
            return  0;
        }
        int res=0;//非空子矩阵的数量,初始为0
        for(int i=0;i<arr.length;i++){
            int[] temp=new int[arr[0].length];
            for(int j=i;j<arr.length;j++){
                Map<Integer,Integer> map=new HashMap();
                map.put(0,1);
                int cur=0;
                for(int k=0;k<arr[0].length;k++){
                    temp[k]=temp[k]+arr[j][k];
                    cur+=temp[k];
                    if(map.containsKey(cur-target)){
                        res+=map.get(cur-target);
                    }
                    map.put(cur,map.getOrDefault(cur,0)+1);
                }
            }
        }
        return res;
    }
}

leetcode152 乘积最大子序列
题目:
在这里插入图片描述
方法1:暴力枚举,超时

class Solution {
    public int maxProduct(int[] nums) {
        int max=Integer.MIN_VALUE;
        for(int i=0;i<nums.length;i++){
            for(int j=i;j<nums.length;j++){
                int temp=1;
                for(int k=j;k<nums.length;k++){
                    temp*=nums[k];
                    max=Math.max(max,temp);
                }
                
            }
        }
        return max;
    }
}

方法2:换一种思路,就是以i结尾的最大可能,虽然通过了,但是速度贼慢,大概超过了百分之5。。我好奇那百分之5怎么做的。。。

class Solution {
    public int maxProduct(int[] nums) {
        int max=Integer.MIN_VALUE;
        //以i结尾的最大累乘积
        for(int i=0;i<nums.length;i++){
            int help=1;
            int k=i;
            while(k>=0){
                help=help*nums[k];
                max=Math.max(max,help);
                k--;
            }
        }
        return max;
    }
}

方法3:我开始想的是递归,从最后一位开始,每一步大概需要以前一个节点结束的子序列的最大值,最小值,结果。。。写出来了动态规划???

class Solution {
    public int maxProduct(int[] nums) {
        int max=Integer.MIN_VALUE;
        //换个思路,尝试一下暴力地柜,好改动态规划
        int[] help=new int[2];
        for(int i=0;i<nums.length;i++){
            if(i==0){
                help[0]=help[1]=nums[0];
                max=Math.max(max,help[0]);
                continue;
            }
            int temp1=help[0];//最大值
            int temp2=help[1];//最小值
            help[0]=Math.max(nums[i],Math.max(temp1*nums[i],temp2*nums[i]));
            help[1]=Math.min(nums[i],Math.min(temp1*nums[i],temp2*nums[i]));
            max=Math.max(max,help[0]);
        }
        return max;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值