如何找到符合下述标准的每个指数的左右子阵列?

时间:2017-08-27 05:34:34

标签: c

存在序列问题,其中对于每个索引 我们在数组中 i 定义了两个数量。

r 成为这样的最大索引 r>=i 以及 i r (包括在内)的子数组要么不减少或不增加。

l 成为 l<=i 以及来自 l i (包括)是非减少或不增加。

现在,我们将索引 i 的点定义为等于

max(|Ai−Al|,|Ai−Ar|) 即可。

请注意,lr可能因每个索引而异。

问题的任务是找到具有最大点的数组A的索引。

我的逻辑:

  1. 首先扫描数组中的所有元素。

  2. 对于每个索引,找到l和r,它们遵循递增或递减的顺序,然后计算该索引的最大点。

  3. 我的问题是这需要花费O(N^2)时间。

    问题可以在更短的时间内完成吗?

1 个答案:

答案 0 :(得分:0)

两个连续的相同数字具有相同的点,并且不会影响任何其他点的点,因此可以假设此方案不存在。

因此,考虑一个没有连续相同数字的输入数组a,可以假设子序列中最长的非减少或不增加是[I1I1] [{{ 1}},I2] ... [Ixn - 1],由index表示,n是数组的长度。每个递减的子序列之后是增加的子序列,反之亦然。

对于任何Ii,索引为Ii的点的点等于max(|AIi - AI(i - 1)|, |AIi - AI(i + 1)|)IiI(i + 1)之间的任何索引都必须小于IiI(i + 1),并且不必考虑。

因此,我们只需要找出所有AIiAI(i + 1)之间的最大值。

经过大量的尝试,我终于接受了我的程序(主要是因为两个int 32之间的差异不一定在signed int 32范围内),代码如下。

#include <stdio.h>

#define MAXN 200002
long long a[MAXN];

long long abs(long long n)
{
    if (n >= 0)
        return n;
    return -n;
}

long long find_score(int size)
{
    int i = 0;
    long long maximum_score = 0;
    while (i < size - 1)
    {
        //Jump over consecutive indentical numbers
        while (a[i + 1] == a[i])
        {
            if (i < size - 1)
                i++;
            else
                break;
        }
        int j = i + 1;
        int inc_or_dec = a[j] > a[i];
        while (j < size - 1 && (!((a[j + 1] > a[j]) ^ inc_or_dec) || a[j + 1] == a[j]))j++;
        if (abs(a[j] - a[i]) > maximum_score)
            maximum_score = abs(a[j] - a[i]);
        i = j;
    }
    return maximum_score;
}

int main()
{
    int n;
    scanf("%d", &n);
    while (n--)
    {
        int num;
        scanf("%d", &num);
        for (int i = 0; i < num; i++)
        {
            scanf("%lld", a + i);
        }
        printf("%lld\n", find_score(num));
    }
    while (1);
    return 0;
}

很高兴知道我的代码中是否存在任何“实现定义”问题。