博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数组中累加和为定值K的最长子数组长度
阅读量:4143 次
发布时间:2019-05-25

本文共 2154 字,大约阅读时间需要 7 分钟。

1、给定一个数组,值全是正数,请返回累加和为给定值k的最长子数组长度。

方法一:暴力求解,求出所有的子数组,共n*(n-1)/2个,然后对每个子数组求和,时间复杂度为O(n^3)

改进方法:因为数组值全是整数,所以长度为n的子数组和一定大于长度为n-1的子数组和(不管多的一项在子数组左边还是右边)。所以可以利用滑动窗口的思想来求解。调整窗口的长度及左右边界使其内的子数组和为k,求出最大窗口长度即可。

例如数组arr的下标为:0...left...right...n-1

left、right分别为滑动窗口的左右边界。

分析:

情况一:当sum[left...right]==k ,此时窗口的长度为最长,再扩展窗口必然会sum>k,记录更新窗口的长度len,并把左边界右移left++减小窗口长度;

情况二当sum[left...right]<k,增加窗口长度,右边界右移right++;

情况三当sum[left...right]>k,没有满足条件,减小窗口长度,左边界右移left++

注意:窗口大小改变时,不要忘记更新sum的值。

时间复杂度:因为只设置了左右两个指针变量,判断以right为结尾的子数组和,遍历整个数组1遍即可,所以时间复杂度为O(n)

public static int getMaxLength(int[] arr, int k) {		if (arr == null || arr.length == 0 || k <= 0) {			return 0;		}		int left = 0;		int right = 0;		int sum = arr[0];		int len = 0;		while (right < arr.length) {			if (sum == k) {				len = Math.max(len, right - left + 1);				sum -= arr[left++];			} else if (sum < k) {				right++;				if (right == arr.length) {//边界判断					break;				}				sum += arr[right];			} else {				sum -= arr[left++];			}		}		return len;	}

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

分析:数组的值可正可负,此时长度为n和长度为n-1的子数组和无法准确比较大小,所以不能再使用上边滑动窗口的方法。

例如数组arr的下标为:0...i...j...n-1

我们可以求出以0位置开始,任意位置结束j的子数组和sum。假设0位置开始,任意位置i结束的子数组和temp,如果存在sum-temp==k,那么i+1...j位置即为所求子数组。为了保证该子数组最长,我们在j位置不变的情况下,需要使i位置出现的尽量靠前。

此时引用一个结构hashmap来保存,key为子数组的和,value为此时子数组结尾元素的位置。根据hashmap的特性key唯一,后出现的temp不会被更新value,也就确保了temp出现的位置尽量靠前。

注意:因为所求子数组是i+1...j位置,为了保证第0位置的元素不被忽略,必须加上map.put(0, -1);

例如arr=[2,3,5,4],k=14,

i=0:sum=2,temp=2-14=-12,map中不存在key==-12的,此时保存map(2,0);

i=1:sum=5,temp=5-14=-9,map中不存在key==-9的,此时保存map(5,1);

i=2:sum=10,temp=10-14=-4,map中不存在key==--4的,此时保存map(10,3);

i=3:sum=14,temp=14-14=0,map中存在key==0的,此时len=3-(-1)=4

如果没有map.put(0, -1); 当i=3时,map中找不到key==0,此时就会返回len=0,而此数组并非无解。

时间复杂度:遍历整个数组一遍,所以为O(n)

public static int maxLength(int[] arr, int k) {		if (arr == null || arr.length == 0) {			return 0;		}		HashMap
map = new HashMap
(); 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); } } return len; }

转载地址:http://lhbti.baihongyu.com/

你可能感兴趣的文章
年薪50万+的90后程序员都经历了什么?
查看>>
2019年哪些外快收入可达到2万以上?
查看>>
【JavaScript 教程】标准库—Date 对象
查看>>
前阿里手淘前端负责人@winter:前端人如何保持竞争力?
查看>>
【JavaScript 教程】面向对象编程——实例对象与 new 命令
查看>>
我在网易做了6年前端,想给求职者4条建议
查看>>
SQL1015N The database is in an inconsistent state. SQLSTATE=55025
查看>>
RQP-DEF-0177
查看>>
MySQL字段类型的选择与MySQL的查询效率
查看>>
Java的Properties配置文件用法【续】
查看>>
JAVA操作properties文件的代码实例
查看>>
IPS开发手记【一】
查看>>
Java通用字符处理类
查看>>
文件上传时生成“日期+随机数”式文件名前缀的Java代码
查看>>
Java代码检查工具Checkstyle常见输出结果
查看>>
北京十大情人分手圣地
查看>>
Android自动关机代码
查看>>
Android中启动其他Activity并返回结果
查看>>
2009年33所高校被暂停或被限制招生
查看>>
GlassFish 部署及应用入门
查看>>