数组中累加和为定值K的最长子数组长度

来源:互联网 发布:买家怎样修改淘宝评价 编辑:程序博客网 时间:2024/05/19 09:12


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<Integer, Integer> map = new HashMap<Integer, Integer>();map.put(0, -1); // importantint 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;}



阅读全文
0 0
原创粉丝点击