前言
当前所有算法都使用测试用例运行过,但是不保证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
再次感谢左大神对我算法的指点迷津!