*大多数朋友如果找到这篇文章,就是来看解答的,所以完整的题目放到文章的最后了。
思路:
1、首先根据题目,大家第一反应就是无脑嵌套遍历所有情况,这样的时间复杂度是O(n^2+n)/2,远远超出O(n)的题目里的要求。
2、其次就是找规律了,这个slice一定发生在最小值周围吗?不一定!比如[-1, -1, 12, -9, 10]。所以不用去思考先找到最小值,再向两边递归的思路了。
3、其实,这里有一个数学证明,就是对于这个最小avg的slice(n,m),m-n+1一定是2或者3,也就是这个最小avg的slice由2个或者3个元素组成。
4、说说为什么会想到上面这个思路:因为题目中说明0<=n<m<N,因此可以得出2个或者3个元素是最小的组合,比如length=3的数组,你无法一次分出2个slice,length=2的数组也一样。为什么要这么去想呢?因为你要“比较”出最小的avg,怎么才能“比较”?那就是必须一次至少有2个slice才能相互比较。那么当N>=4时,我们就能一次最少分出2个slice。举length=4的例子,情况有以下几种:slice(0,1) slice(1,2) slice(2,3) slice(0,2) slice(1,3) slice(0,3)。可以看出前3个是2个元素的slice,后4-6个是3个元素的slice,最后一个是4个元素的slice。再来回想以下我们的命题,就是“min avg一定存在2/3个元素的slice中”,那么反过来就是length>=4的slice一定不是min avg。这个结论是肯定的,因为当元素>=4个时,我们把它分为2个sliceA sliceB,这两个slice肯定有一个大于另一个,或者2个相等。那么我们得出结论当sliceA>sliceB时,取sliceB为当前min avg的slice(反之亦然),当sliceA=sliceB时,则sliceA和sliceB都为当前min avg的slice。显然,原始slice已经被拆分了,它的存在是不正确的(子slice更优)或者是可被替代的(子slice和它相等)。如此继续拆分slice直到,length=2或者3时,我们就无法确定这个slice不是最优的,因此要去计算和记录它,并和其他slice的比较。
5、得到这个结论后,算法就变得异常简单,就是遍历数组,求连续2或者3个元素的avg,直接看到代码吧!
class Solution {
public int solution(int[] A) {
// write your code in Java SE 8
double min = 10001;
int minIndex = -1;
for (int i = 0; i < A.length - 1; i ++) {
double current2 = (A[i] + A[i + 1]) / 2d;
if (current2 < min) {
min = current2;
minIndex = i;
}
if (i != A.length - 2) {
double current3 = (A[i] + A[i + 1] + A[i + 2]) / 3d;
if (current3 < min) {
min = current3;
minIndex = i;
}
}
}
return minIndex;
}
}
下面是原题:
Task description
A non-empty zero-indexed array A consisting of N integers is given. A pair of integers (P, Q), such that 0 ≤ P < Q < N, is called a slice of array A (notice that the slice contains at least two elements). The average of a slice (P, Q) is the sum of A[P] + A[P + 1] + ... + A[Q] divided by the length of the slice. To be precise, the average equals (A[P] + A[P + 1] + ... + A[Q]) / (Q − P + 1).
For example, array A such that:
A[0] = 4
A[1] = 2
A[2] = 2
A[3] = 5
A[4] = 1
A[5] = 5
A[6] = 8
contains the following example slices:
- slice (1, 2), whose average is (2 + 2) / 2 = 2;
- slice (3, 4), whose average is (5 + 1) / 2 = 3;
- slice (1, 4), whose average is (2 + 2 + 5 + 1) / 4 = 2.5.
The goal is to find the starting position of a slice whose average is minimal.
Write a function:
class Solution { public int solution(int[] A); }
that, given a non-empty zero-indexed array A consisting of N integers, returns the starting position of the slice with the minimal average. If there is more than one slice with a minimal average, you should return the smallest starting position of such a slice.
For example, given array A such that:
A[0] = 4
A[1] = 2
A[2] = 2
A[3] = 5
A[4] = 1
A[5] = 5
A[6] = 8
the function should return 1, as explained above.
Assume that:
- N is an integer within the range [2..100,000];
- each element of array A is an integer within the range [−10,000..10,000].
Complexity:
- expected worst-case time complexity is O(N);
- expected worst-case space complexity is O(N), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.
本文探讨了一个算法问题,目标是在给定数组中找到具有最小平均数的连续子数组,通过数学证明和简单算法实现,解决复杂度限制下的高效搜索策略。
299

被折叠的 条评论
为什么被折叠?



