【算法】【矩阵与数组模块】求数组中和为给定值的最长子数组长度系列问题

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
给定数组arr,数组值为整数,给定num,求arr中和为num的最长子数组长度
进阶问题1
给定数组arr,数组值为整数,求arr中正数和负数数量相同的最长子数组长度
进阶问题2
给定数组arr,数组值为0和1,求arr中0和1数量相同的最长子数组长度

解决方案

原问题:
1、遍历arr,申请一个sum变量,用来累加arr[i]
2、每一次遍历,求出以arr[i]为底的所有子数组中是否存在和的num的数(遍历map,用sum减去每一个map中的key,得到的数检查是否等于num),如果存在则更新最大长度max,本次遍历结束后,将sum值存入map中,map的key存sum,value存i,若冲突则保留第一个i
3、遍历结束后,maxlen就是答案
进阶问题1:
1、正数改为1,负数改为0,求arr中,和为0的最长子数组长度
进阶问题2:
1、0改为负数,求arr中,和为0的最长子数组长度

代码编写

java语言版本

    /**
     * 求累加和为指定值的最长子数组长度
     * @param arr
     * @param num
     * @return 1:起点index,2、终点index 3、最大长度
     */
    public static int[] myGetMaxLenth(int[] arr, int num){
        if (arr == null || arr.length == 0){
            return null;
        }
        int res = 0;
        // 以某个数为底的和 -> 出现这个和的第一次出现的index
        Map<Integer, Integer> map = new HashMap<>();
        // 初始化需要添加一个以和为0的index为-1,也就是sum本身
        map.put(0, -1);
        int[] headAndTail = new int[3];
        int sum = 0;
        int maxLen = 0;
        for (int i = 0; i < arr.length; i++){
            sum += arr[i];
            int key = sum - num;
            // 先检验0
            if (map.containsKey(key)){
                if (i - map.get(key) > maxLen){
                    headAndTail[0] = map.get(key);
                    headAndTail[1] = i;
                    maxLen = i - map.get(key);
                    headAndTail[2] = maxLen;
                }
            }
            map.putIfAbsent(sum, i);
        }
        return headAndTail;
    }


    /**
     * 获取数组中正负数数量相同的最长子数组长度
     * @param arr
     * @return
     */
    public static int[] myGetMaxLengthFromPG(int[] arr){
        if (arr == null || arr.length == 0){
            return null;
        }
        for (int i = 0; i < arr.length; i++){
            if (arr[i] < 0){
                arr[i] = -1;
            }else if (arr[i] > 0){
                arr[i] = 1;
            }
        }
        return myGetMaxLenth(arr, 0);
    }


    /**
     * 数组只有0和1,求0和1个数相同的最长子数组长度
     * @param arr
     * @return
     */
    public static int[] myGetMaxLengthFrom01(int[] arr){
        if (arr == null || arr.length == 0){
            return null;
        }
        for (int i = 0; i < arr.length; i++){
            if (arr[i] == 0){
                arr[i] = -1;
            }
        }
        return myGetMaxLenth(arr, 0);
    }

    public static void main(String[] args) {
        int[] ints = {1, 3, 2, 5, 4, 7, 8};
        int[] ints1 = {-3, -1, -4, 6, 3, -3, 5, 6, 0};
        int[] ints2 = {0, 1, 1, 0, 0, 0, 0, 1, 0};

        System.out.println(myGetMaxLenth(ints, 8));
        System.out.println(myGetMaxLengthFromPG(ints1));
        System.out.println(myGetMaxLengthFrom01(ints2));

    }

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

这道题是我第二次面试的时候遇到的,当时还没有刷完题,就遇到了这道题,有些类似,只不过又加了二叉树的遍历在里面
该题记住两个重点:
1、求最大XXX值,应该从低维度开始遍历,比如以arr[i]为底求最大长度,map存储的信息非常重要,只要记住map中存储的信息代表什么意思,这道题就没有难度了
2、记得map初始化需要有一个(0,-1)代表从头开始和为0

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

元空间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值