笔试面试算法经典-未排序正整数数组中累加和为给定值的子数组
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]。
例如上面数组中:刚开始时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的子数组。
解法2的适用更广,不仅可以用在未排序的正整数数组中,还可以适用于数组中出现负值,零值的情况。
给定一个数组 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的适用更广,不仅可以用在未排序的正整数数组中,还可以适用于数组中出现负值,零值的情况。
相关文章推荐
- 笔试面试算法经典--打印数组中相加和为给定值的二元组及三元组(Java)
- 左神算法 未排序正数组中累加和为给定值的最长子数组长度
- 这是一个我面试某公司的算法题目:对一个字符数组进行排序,根据给定的字符,大于它的,放在数组的左边,小于它的,放在数组的右边,且数组中的元素之间的相对位置要保持不变。
- 【LeetCode-面试算法经典-Java实现】【004-Median of Two Sorted Arrays(两个排序数组的中位数)】
- 左神算法 未排序数组中累加和为给定值的最长子数组系列问题
- 【LeetCode-面试算法经典-Java实现】【026-Remove Duplicates from Sorted Array(删除排序数组中的重复元素)】
- 【LeetCode-面试算法经典-Java实现】【081-Search in Rotated Sorted Array II(搜索旋转的排序数组)】
- 笔试面试算法经典-找到数组中出现次数大于N/k的数(Java)
- 【LeetCode-面试算法经典-Java实现】【108-Convert Sorted Array to Binary Search Tree(排序数组转变为平衡二叉树)】
- 整型数组处理算法(九)给定任意一个正整数,求比这个数大且最小的“不重复数”[2014百度笔试题]
- 笔试面试算法经典--数组partition调整使数组的左部分单调有序
- 整型数组处理算法(九)给定任意一个正整数,求比这个数大且最小的“不重复数”(性能优化)[2014百度笔试题]
- 整型数组处理算法(九)给定任意一个正整数,求比这个数大且最小的“不重复数”(性能优化)[2014百度笔试题]
- 【LeetCode-面试算法经典-Java实现】【088-Merge Sorted Array(合并排序数组)】
- 笔试面试算法经典-打印n个数组中最大的topk
- 笔试面试算法经典--连续子数组的最大乘积及连续子数组的最大和(Java)
- 【LeetCode-面试算法经典-Java实现】【075-Sort Colors (颜色排序)】
- 【LeetCode-面试算法经典-Java实现】【033-Search in Rotated Sorted Array(在旋转数组中搜索)】
- 每日一道算法题:Google 2009年某笔试题:求出元素位于0到9之间的集合A中大于某个给定正整数K的组成的最小正整数。
- 【LeetCode-面试算法经典-Java实现】【082-Remove Duplicates from Sorted List II(排序链表中删除重复元素II)】