您的位置:首页 > 职场人生

笔试面试算法经典-未排序正整数数组中累加和为给定值的子数组

2017-04-13 23:15 615 查看
【题目】

给定一个数组 arr,该数组无序,但每个数均为正数,再给定一个正数 k 。求 arr 的所有子数组中所有元素相加为k的最长子数组长度。例如,arr=[1,2,1,1,1],k=3。累加和为3的子数组为[1,2] ,[2,3], [1,1,1]。

解法1(时间复杂度O(N)空间复杂度O(1))

思路:left,right来指向数组中的某一个区间,sum用来保存left和right区间中的值,由于数组中的元素都为正数,当right向右移动的时候,sum的值增加,left向右移动时,区间变小sum的值减小。因此可以通过改变left,right的值来遍历数组的所有子区间。

例如上面数组中:刚开始时left=0,right=0,sum=arr[right]=1,此时sum<3,此时移动right=1,sum+=arr[right]=3,所有子数组[1,2]的值符合,此时left向左移动,sum-=arr[left]=2,sum<3,right++,指向1,此时sum+=arr[right]=3,子数组[1,2]符合。重复操作直到right到达数组尾,就可以得到所有值为3的子数组。

public static void longestsumofk1(int arr[],int k)
{
if(arr==null||arr.length==0)
return;
int left=0,right=0;
int sum=arr[0];
//初始时将sum赋值为arr[right].
while(right<arr.length)
{
if(sum==k)
{
//如果sum==k打印left-right之间的子数组    sum是区间left-right元素的和
for(int i=left;i<=right;i++)
System.out.print(arr[i]+" ");
System.out.println();
sum-=arr[left];
left++;
//向右压缩区间sum的值减小。
}
else if(sum<k)
{
right++;
if(right==arr.length)
break;
sum+=arr[right];
//如果sum的值<k向右扩展区间,使得sum值增大
}
else {
//否则利用left向右压缩区间。sum值减小。
sum-=arr[left];
left++;
}
}
}


解法2(时间复杂度O(n),空间复杂度O(n))

利用性质:sum[i…k] = arr[i]+arr[i+1]….+arr[j]+arr[j+1]+…arr[k] , sum[i…j] = arr[i]+arr[i+1]+…arr[j],如果sum[i…k] – sum[i…j] = result(result为给定的值),那么可知:arr[j+1]+arr[j+2]+…arr[k]=result,因此可以利用上面的性质来遍历数组用 sum来保存遍历过的的数组的所有元素的和,如果hashmap中没有sum值以及当前的数组下标作为(key,value)存放到hashmap中,查看hashmap中是否有sum-k的值存在,如果存在获取其value值,则可知区间[value , j]为符合条件的子数组区间(j为当前数组下标)。

public static void longestsumofk(int arr[],int k)
{
if(arr==null||arr.length==0)
return;
int sum=0,max=0;
HashMap<Integer,Integer> hashMap=new HashMap<Integer, Integer>();
hashMap.put(0,-1);
//预处理中将(0,-1)放入到hashmap中,可以求出从数组0下标开始的子数组。
for(int i=0;i<arr.length;i++)
{
sum+=arr[i];
if(!hashMap.containsKey(sum))
{
hashMap.put(sum, i);
//如果当前数组中不存在sum值将其同下标一起放到hashmap中
}
if(hashMap.containsKey(sum-k))
{
//如果hashmap中存在sum-k由上面的分析可知获取sum-k的value值,
//从sum-k的value值到当前数组下标是符合条件的子数组区间
int j=hashMap.get(sum-k)+1;
for(;j<=i;j++)
{
System.out.print(arr[j]+" ");
}
System.out.println();
}
}
}


解法2的适用更广,不仅可以用在未排序的正整数数组中,还可以适用于数组中出现负值,零值的情况。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐