【问题标题】:minimum slice position - Order N algorithm最小切片位置 - 阶 N 算法
【发布时间】:2015-07-30 21:17:27
【问题描述】:

给出了一个由 N 个整数组成的非空零索引数组 A。一对整数 (P, Q),使得 0 ≤ P

写一个函数:

int 解(int A[], int N);

给定一个由 N 个整数组成的非空零索引数组 A,返回具有最小平均值的切片的起始位置。 如果有多个切片具有最小平均值,则应返回该切片的最小起始位置。

假设:

N 是 [2..100,000] 范围内的整数; 数组 A 的每个元素都是 [−10,000..10,000] 范围内的整数。 复杂性:

预期的最坏情况时间复杂度为 O(N); 预期的最坏情况空间复杂度为 O(N),超出输入存储(不计算输入参数所需的存储)。

你能只发布订单 N 的解决方案吗?

【问题讨论】:

  • A中的整数都是正数吗?
  • 不一定,我加了更多信息
  • 我确信没有 N 阶解决方案

标签: algorithm


【解决方案1】:

如果A 仅有正数,您可以不用这样:

pos = 0
min_avg = A[0] + A[1]
for (i=2; i<N; i++)
    m = A[i-1] + A[i]
    if (m < min_avg)
        min_avg = m
        pos = i-1
return pos

这只是取两个数字的切片的平均值,因为较大切片的平均值不能小于较小切片的最小值。

如果A有负数,你可以先向上调整所有值:

offset = min(A)
for (i=0; i<N; i++)
    A[i] -= offset

结合之前的算法:

offset = min(A) * 2              (because we're adding two numbers below)
pos = 0
min_avg = A[0] + A[1] - offset
for (i=2; i<N; i++)
    m = A[i-1] + A[i] - offset
    if (m < min_avg)
        min_avg = m
        pos = i-1
return pos

【讨论】:

  • “较大切片的平均值不能小于较小切片的最小值。”我不确定你的意思是什么。当你取所有东西时,[1,10,1] 有其最小平均值,而不是更小的切片。
  • @Teepeemm 你是对的,在某些情况下,较大的切片可能具有较小的平均值,但这些情况并不常见。请看我的其他回答。
  • 具体来说,对于一个三数序列[a, b, c],它必须满足:(a+b)/2 &gt; c(b+c)/2 &gt; a(a+b+c)/3 小于任何其他平均值。
  • 考虑到这一点,我认为这个想法是正确的。您只需检查所有长度为 3 的切片以及长度为 2 的切片。
【解决方案2】:

我认为你是对的,我能做的最好的就是 O(N2) 解决方案(这是在 Python 中):

from random import randint

N = 1000
A = [randint(-10000, 10000) for _ in xrange(N)]

def solution(A, N):
    min_avg = 10001
    for p in xrange(N):
        s = A[p]
        for q in xrange(1,N-p):
            s += A[p+q]
            a = s / (q+1.)
            if a < min_avg:
                min_avg = a
                pos = (p, q+1)
    return pos

print solution(A, N)

但是,较大切片的平均值倾向于原始范围的平均值(中间)。在这种情况下,平均值为零,介于 -10000 和 10000 之间。大多数情况下,最小的平均值是两个值的切片,但有时它可以是三个值的切片,很少是更多值.所以我认为我之前的答案在大多数(> 90%)的情况下都有效。这真的取决于数据值。

【讨论】:

    【解决方案3】:
        #include <assert.h>
        struct Slice { unsigned P, Q; };
        struct Slice MinSlice( int A[], unsigned N ) {
            assert( N>=2 );
            // find min slice of length 2
            unsigned P = 0;
            double min_sum = A[P] + A[P+1];
            for (unsigned i = 1; i < N-1; ++i)
                if ( min_sum > A[i] +A[i+1] ) {
                    P = i;
                    min_sum = A[P] + A[P+1];
                }
            unsigned Q = P+1;
            double min_avg = min_sum / 2;
            //extend the min slice if the avg can be reduced.
            //(in the direction that most reduces the avg)
            for (;;) {
                if ( P > 0 && ( Q >= N-1 || A[P-1] <= A[Q+1] ) ) {
                    //reducing P might give the best reduction in avg
                    double new_sum = A[P-1] + min_sum;
                    double new_avg = new_sum / (Q - P + 2);
                    if ( min_avg < new_avg )
                        break;
                    min_sum = new_sum; 
                    min_avg = new_avg; 
                    --P;
                 } else if ( Q < N-1 && ( P <= 0 || A[P-1] >= A[Q+1] ) ) {
                    //increasing Q might give the best reduction in avg
                    double new_sum = min_sum + A[Q+1];
                    double new_avg = new_sum / (Q - P + 2);
                    if ( min_avg < new_avg )
                        break;
                    min_sum = new_sum; 
                    min_avg = new_avg; 
                    ++Q;
                 } else
                     break;
            }
            struct Slice slice = { .P = P, .Q= Q };
            return slice;
        }
    

    【讨论】:

    • 请解释一下。
    猜你喜欢
    • 1970-01-01
    • 2010-10-26
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 2019-03-06
    相关资源
    最近更新 更多