import java.util.HashMap;
/**
*
* 2、给定一个数组,值可以为正、负和0,请返回累加和为给定值k的最长子数组长度。
* 咱们可以反推,比如:1- 100,数组和为1000.
* 要求最长和为300的子数组,我可以反着求第一次出现和700的子数组,因为是第一次那必须是最短的长度。
* 这样反过来,剩下的 300 必须是最长的子数组。
*
*
* 比如: 求k= 6 时,最长子序列
* index : 0 1 2 3 4 5
* value : 4 3 2 5 1 6
* sum : 4 7 9 14 15 21
*
* 利用 map 存入 sum - index ; sum当为key,index当为value
* 每次循环的时候,判断下 利用sum-k是否存在 map中(因为是从前往后遍历的,随意如果存在的话,必须是最短的和为“sum-k”子序列,
* 相反的剩下的必须是最长的和为k的子序列)。遍历到(i)则为终止index。
*
* 注意点:
* 必须首先设置map.put(0, -1)。
* 因为由上面可知道:当我们判断(sum-k)存在的时候获得当前map下面的value值也就是 把(sum-k)作为key,获得其value。
* 其实,这个value就是 数组的index。
* 假设 这个index = i;而我们需要的最长和为k的数组是从i+1 到当前遍历的数组index位置。长度:len = i-map.get(sum-k)
*
* 举例:由上面的例子为例,当我们遍历到index = 4时,sum = 15。而 sum - k = 15 - 6 = 9;从而,我们判断map存在 以9为键
* 的map,其value = 2。所以,我们的范围是从 2+1 = 3到4。
* 所以,如果,不首先存入map.put(0,-1)。那么以首字符开头的最大和为k的长度将少了一个index为0 的字符。因为 -1 +1 = 0;
*
*
* @author xiaodong
*
*/
public class Problem_02_LongestSumSubArrayLength
{
public static int maxLength(int[] arr, int k)
{
if (arr == null || arr.length == 0)
{
return 0;
}
HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(0, -1); // important 代表一个数都没有的境况下,
int len = 0;
int sum = 0;
for (int i = 0; i < arr.length; i++)
{
sum += arr[i];
if (map.containsKey(sum - k))
{
len = Math.max(i - map.get(sum - k), len);
}
if (!map.containsKey(sum))
{
map.put(sum, i); //value --- index
}
}
return len;
}
public static int[] generateArray(int size)
{
int[] result = new int[size];
for (int i = 0; i != size; i++)
{
result[i] = (int) (Math.random() * 11) - 5;
}
return result;
}
public static void printArray(int[] arr)
{
for (int i = 0; i != arr.length; i++)
{
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args)
{
int[] arr = generateArray(20);
printArray(arr);
System.out.println(maxLength(arr, 10));
}
}
题目三:给定一个数组,值可以为正、负和0,请返回累加和为给定值k的最长子数组长度。
最新推荐文章于 2021-08-14 14:14:13 发布