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

    xiaoxiao2021-04-14  77

    【题目】 给定一个数组 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的适用更广,不仅可以用在未排序的正整数数组中,还可以适用于数组中出现负值,零值的情况。

    转载请注明原文地址: https://ju.6miu.com/read-670738.html

    最新回复(0)