题目三:给定一个数组,值可以为正、负和0,请返回累加和为给定值k的最长子数组长度。

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));

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Terry_dong

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

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

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

打赏作者

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

抵扣说明:

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

余额充值