最近刷LeetCode题目的一些思路,题目信息
返回 A
的最短的非空连续子数组的长度,该子数组的和至少为 K
。
如果没有和至少为 K
的非空子数组,返回 -1
。
示例 1:
输入:A = [1], K = 1 输出:1
示例 2:
输入:A = [1,2], K = 4 输出:-1
示例 3:
输入:A = [2,-1,2], K = 3 输出:3
提示:
1 <= A.length <= 50000
-10 ^ 5 <= A[i] <= 10 ^ 5
1 <= K <= 10 ^ 9
--------------------------------------------------------------------------------------
意思很简单,就是最少连续多少个子数组的数据相加和大于等于K,先看一个简单的处理方式,只不过时间复杂度太大,总是超时
public int shortestSubarray(int[] A, int K) { int retNumber = -1; for(int k=1; k<A.length + 1; k++){ for(int i=0; i< A.length; i++){ if(A[i] <= 0){ continue; } int total = 0; int number = k; if(number > A.length - i){ number = A.length - i; } for(int j=0;j<number; j++){ total += A[i + j]; if(total <= 0){ break; } if(total >= K){ return j+1; } } } } return retNumber; }
上面的方法思路,理解起来也很简单,时间复杂度达到了O(n^3),实在太高了,所以只能更换思路重新处理
--------------------------------------------------------------------------------------
这个思路是别人的,从数据第一个成员开始逐个求和,其实就是一个新的数组,不过这个数组内容是给定数组前n个数据和,这样通过和的差值比对就可以得到某个区间的数据和其实是符合要求的,这样就可以找到符合条件的最小区间
public int shortestSubarray(int[] A, int K) { int retNumber = Integer.MAX_VALUE; TreeMap<Long,Integer> sumDataMap = new TreeMap<>(); long sum = 0; long smallSum = A[0]; for(int i=0; i<A.length; i++){ if(A[i] >= K){ return 1; } sum += A[i]; if (sum >= K) { if (i + 1 < retNumber) retNumber = i + 1; } long sub = sum - K; while (!sumDataMap.isEmpty()){ Map.Entry<Long, Integer> entry = sumDataMap.floorEntry(sub); if(entry == null){ break; } long key = entry.getKey(); int j = entry.getValue(); sumDataMap.remove(key); if(i - j < retNumber){ retNumber = i - j; } } if(sum < smallSum){ sumDataMap.clear(); smallSum = sum; } sumDataMap.put(sum,i); } if(retNumber == Integer.MAX_VALUE){ retNumber = -1; } return retNumber; }