【问题标题】:Find the maximum value of minimum of each subarray of non fixed length x where 1<= x <= N求非固定长度 x 的每个子数组的最小值的最大值,其中 1<= x <= N
【发布时间】:2015-06-21 05:13:31
【问题描述】:

面试题:

给你一个数组中的 N 个数字。一个数字的 是数组的非空连续段。组的大小是该组中数字的数量。

A 为组中的最小数。任务是为每个x (1 x 组中A的最大值em>x.

例如,如果 N = 3 并且数组是 [1,2,3],那么答案将是 3 (x = 1), 2 (x = 2), 1 ( x = 3)。

数组中的数字可以重复(例如N = 7,数组可以是[1,2,3,4,5,4,6]。

为了解释,下面的 C 代码是一个幼稚的解决方案:

#include <stdio.h>

int main() {
    int a[] = {6,1,3,2,5,4,7};
    size_t N = sizeof a / sizeof *a;

    for (size_t i=0; i<N; ++i) printf("%d ", a[i]); puts("\n");

    size_t group_size, start, i;
    int max, min;
    for (group_size = 1; group_size <= N; ++group_size) {
        max = 0;
        for (start = 0; start <= N - group_size; ++start) {
            min = a[start];
            for (i = start + 1; i < start + group_size; ++i) {
                if (a[i] < min)
                    min = a[i];
            }
            if (min > max)
                max = min;
        }
        printf("%d ", max);
    }

    return 0;
}

输出:

6 1 3 2 5 4 7

7 4 4 2 2 1 1

【问题讨论】:

  • 我多次阅读您的描述,但仍然无法找出您要指定的内容。您能否在示例答案中详细说明您是如何得出“3,2,1”的?
  • @SpecialSauce size =1 可能的连续子数组 - {1},{2},{3} ,现在最小值的最大值将为 3 ,size = 2 ,可能的连续子数组 {1,2 } {2,3} 。现在最小值的最大值将是 2 ,同样对于 size = 3 ,最小值的最大值将是 1,所以答案是 3,2,1

标签: algorithm dynamic-programming


【解决方案1】:

线性时间解决方案的非常简短的草图:对于每个数组元素,计算该元素最小的最大组的大小。 (通过将两个相等元素中的第一个视为较小元素来打破平局。)使用退化桶排序在线性时间内按相关大小对元素进行排序。按大小从大到小扫描元素,输出目前看到的最大元素(即组大小满足当前阈值的最大元素)。

棘手的步骤是计算组大小。我们保留一个堆栈并从头到尾扫描数组。对于每个元素,我们弹出大于它的堆栈元素,从而结束它们的组。这是6 1 3 2 5 4 7 上的跟踪记录。

stack: (-inf @ -1)  {sentinel}

6 1 3 2 5 4 7 -inf  {sentinel}
^
stack: (-inf @ -1), (6 @ 0)

6 1 3 2 5 4 7 -inf
  ^
pop (6 @ 0): group size of 6 is (1 - (-1)) - 1 = 1
stack: (-inf @ -1), (1 @ 1)

6 1 3 2 5 4 7 -inf
    ^
stack: (-inf @ -1), (1 @ 1), (3 @ 2)

6 1 3 2 5 4 7 -inf
      ^
pop (3 @ 2): group size of 3 is (3 - 1) - 1 = 1
stack: (-inf @ -1), (1 @ 1), (2 @ 3)

6 1 3 2 5 4 7 -inf
        ^
stack: (-inf @ -1), (1 @ 1), (2 @ 3), (5 @ 4)

6 1 3 2 5 4 7 -inf
          ^
pop (5 @ 4): group size of 5 is (5 - 3) - 1 = 1
stack: (-inf @ -1), (1 @ 1), (2 @ 3), (4 @ 5)

6 1 3 2 5 4 7 -inf
            ^
stack: (-inf @ -1), (1 @ 1), (2 @ 3), (4 @ 5), (7 @ 6)

6 1 3 2 5 4 7 -inf
              ^
pop (7 @ 6): group size of 7 is (7 - 5) - 1 = 1
pop (4 @ 5): group size of 4 is (7 - 3) - 1 = 3
pop (2 @ 3): group size of 2 is (7 - 1) - 1 = 5
pop (1 @ 1): group size of 1 is (7 - (-1)) - 1 = 7
stack: (-inf @ -1), (inf @ 7)

【讨论】:

    【解决方案2】:

    这是一个 O(n2) 的解决方案。

    设置输出数组为空,输入数组a为初始值。

    a 不为空:

    • 计算 a 的最大值并添加到输出数组的开头
    • a 执行收缩操作,其中每个元素 a[i] 设置为 a[i] 和 a[i+1] 的最小值,并移除最后一个元素

    例子:

    output = []
    a = [1,2,3,4,5,4,6]
    output = [6] // add max of a to start of output array
    a = [1,2,3,4,4,4]  // shrink array
    output = [4,6] // add max of a to start of output array
    a = [1,2,3,4,4]  // shrink array
    output = [4,4,6] // add max of a to start of output array
    a = [1,2,3,4]  // shrink array
    output = [4,4,4,6] // add max of a to start of output array
    a = [1,2,3]  // shrink array
    output = [3,4,4,4,6] // add max of a to start of output array
    a = [1,2]  // shrink array
    output = [2,3,4,4,4,6] // add max of a to start of output array
    a = [1]  // shrink array
    output = [1,2,3,4,4,4,6] // add max of a to start of output array
    a = []
    

    在循环的第一次迭代开始时,a 将包含所有长度为 1 的组中的最小值(只是初始值)。在第二次迭代开始时,它将包含所有长度为 2 的组中的最小值,依此类推。

    在每次迭代中,元素 a[i] 到 a[j] (min(a[i]...a[j])) 的最小值将等于

    min(min(a[i]...a[j-1]),min(a[i+1]...a[j]))

    因此您可以根据长度为 n-1 的相邻组计算长度为 n 的组的最小值。

    C 代码:

    #include <stdio.h>
    
    int main() {
        int a[] = {6,1,3,2,5,4,7};
        size_t i, N = sizeof a / sizeof *a;
    
        for (i=0; i<N; ++i) printf("%d ", a[i]); puts("\n");
    
        while(N > 0)
        {
            int max = a[0];
            for(i = 0; i < N - 1; i++)
            {
                if(a[i+1] > max)
                   max = a[i+1];
                a[i] = a[i+1] < a[i] ? a[i+1] : a[i];
            }
            printf("%d ", max);
            N--;
        }
    
        return 0;
    }
    

    Demo

    【讨论】:

    • [6,1,3,2,5,4,7] -&gt; [7,4,4,2,2,1,1]有效吗
    • @ooga,是的。每次迭代的 a 值(通过应用收缩操作找到)为 [6,1,3,2,5,4,7], [1,1,2,2,4,4], [1,1 ,2,2,4], [1,1,2,2], [1,1,2], [1,1], [1] 并且每个数组的最大值为 [7,4,4 ,2,2,1,1]
    【解决方案3】:

    这个问题只是用花哨的词。您需要计算的是反向排序数组中的第 (x - 1) 个最大数。

    要看到这个,假设你有一个表单数组:

    A = [12, 14, 26, 50, 43];
    

    如果你对它进行排序,它会变成

    A' = [12, 14, 26, 43, 50];
    

    现在,任何需要最大化最小值的子数组,将是从末尾开始时长度为 x 的子数组。因为对于所有其他可能的子数组,必须存在小于从 end 开始的第 x 个元素的元素,从而减少最小值。

    所以要得到你的答案,你只需对数组进行反向排序,索引 (x - 1) 处的元素就是你的答案。

    A'' = [50, 43, 26, 14, 12]
    

    可以很容易地计算出每个非固定长度x的子数组的最大值和最小值。

    编辑:

    例如查看 x 从 1 到 3

     Length 1: 50
     Length 2: 43
     Length 3: 26
    

    等等。

    EDIT2:

    这只有在所有元素都是唯一的情况下才有效。

    【讨论】:

    • 我对这个问题的理解是输入[1, 2, 2, 1, 2]应该给出输出[2, 2, 1, 1, 1]。这不对吗?如果是,那么您的答案如何适合。
    • 你的答案是错误的,考虑 N = 7 的情况,数字是 - 1,2,3,4,5,4,6 反向排序会变成 6,5,4,4, 3,2,1 ,所以根据你的说法,当 x= 2 答案是 5 但在这种情况下答案是 4。请在否决任何问题之前检查您的答案。
    • 首先,我从来没有否决任何问题。即使您的解释不充分,我也试图回答。
    • @user3703826 在您给出的示例中,答案仍然是 5。长度为 2 的子数组将是 {5, 6},因为最小元素是 5。
    • @harsh ,段应该是连续的。
    猜你喜欢
    • 2016-03-02
    • 2021-06-12
    • 2021-11-25
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 2017-08-01
    • 1970-01-01
    相关资源
    最近更新 更多