package matrix_and_array;
import java.util.*;
/**
* 题目:未排序数组中累加和为给定值的最长子数组长度,
*
* 问题描述:给定一个数组 arr ,该数组无序,每个值可正,可负,可0,再给定一个正数 k。求 arr 所有子数组中所有元素相加和为 k 的最长子数组长度。
*
* 例如: arr = [1,2,3,3,1],k=6. 累加和为6的最长子数组为[1,2,3],所以返回结果为 3
*
* @author sgy
*
*/
public class Maxsub_len2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int arr[] = { 1, 2, 3, 3, 1 };
// System.out.println(getMaxLength(arr, 6));
int a[] = getMaxLength(arr, 6);
int left = 0, right = 0;
if (a != null) {
left = a[0];
right = a[1];
for (int i = left; i <= right; ++i)
System.out.print(arr[i]+" ");
}else
System.out.println("没有符合条件的数据!");
}
/**
* 为了说明解法,先定义s的概念,s(i)代表子数组arr[0...i]所有元素的累加和。
* 那么arr[j...i](0<=j<=i<arr.length)的累加和为s(i)-s(j-1)
*
* 本方法输出最长的序列,注释掉的代码为单纯求长度。
*
* 时间复杂度:O(N)
* 空间复杂度:O(N)
*
*/
public static int[] getMaxLength(int arr[], int k) {
if (arr == null || arr.length == 0) {
return null;
}
int a[] = { 0, 0 };
int len = 0;
int sum = 0;
//Map记录当前位置的累加和s(i)
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int i = 0; i < arr.length; ++i) {
map.put(0, -1);
sum += arr[i];
if (map.containsKey(sum - k)) {
// len = len > i-map.get(sum-k)?len:i-map.get(sum-k);
if (len < i - map.get(sum - k)) {
a[0] = map.get(sum - k) + 1;
a[1] = i;
len = i - map.get(sum - k);
}
}
if (!map.containsKey(sum)) {
map.put(sum, i);
}
}
if (len == 0) { //没有找到符合条件的数据,返回空数组
return null;
} else
return a;
}
}
补充题目【1】:
问题描述:给定一个数组 arr ,该数组无序,每个值可正,可负,可0。求 arr 所有子数组中正数与负数个数相等的最长子数组长度。
解法:可以把原数组中的正数变成1,负数变成-1 , 0 保持不变,最终问题求累加和为0的最长子数组
补充题目【2】:
问题描述:给定一个数组 arr ,该数组无序,每个值只有1或者0两种取值。求 arr 所有子数组中0和1个数相等的最长子数组长度。
解法:可以把原数组中的0变成1,1保持不变,最终问题求累加和为0的最长子数组
代码参考上面,略!