单调对 - Codility

时间:2014-04-16 15:05:31

标签: java algorithm

我只是在Codility,并且遇到了一项任务,我无法找到目标O(n)效率的解决方案;我的解决方案运行O(n2)。如果有人能给我一个如何让它跑得更快的提示,我会很高兴的。这是任务。

给出了由N个整数组成的非空零索引数组A.

单调对是一对整数(P,Q),使得0≤P≤Q<1。 N和A [P]≤A[Q]。

目标是找到其指数最远的monotonic_pair。更确切地说,我们应该最大化Q-P值。仅找到距离就足够了。

例如,考虑数组A:

A[0] = 5
A[1] = 3
A[2] = 6
A[3] = 3
A[4] = 4
A[5] = 2

有11个monotonic_pairs:(0,0),(0,2),(1,1),(1,2),(1,3),(1,4),(2,2), (3,3),(3,4),(4,4),(5,5)。对中的最大距离是3(1,4)。

写一个函数:

class Solution {public int solution(int [] A); }

给定N个整数的非空零索引数组A,返回任何monotonic_pairs中的最大距离。

例如,给定:

A[0] = 5
A[1] = 3
A[2] = 6
A[3] = 3
A[4] = 4
A[5] = 2

该函数应返回3,如上所述。

假设:

N是[1..300,000]范围内的整数; 数组A的每个元素都是[-1,000,000,000..1,000,000,000]范围内的整数。 复杂度:

预期的最坏情况时间复杂度为O(N); 预期的最坏情况空间复杂度是O(N),超出输入存储(不计入输入参数所需的存储)。 可以修改输入数组的元素。

我的第一个想法解决方案(在O(n2)中运行):

    public static int solution(int[] A) {
    int max = 0;
    for(int i=0; i<A.length-1; i++) {
        for(int j=i+1; j<A.length; j++) {
            if(A[j] >= A[i] &&
                    (j - i) >= max) {
                max = j - i;
            }
        }
    }
    return max;
}

5 个答案:

答案 0 :(得分:5)

创建一个包含降序最大值的临时数组:

int[] top = new int[A.length];
int max = -Integer.MAX_VALUE;
for (int i=A.length-1; i>=0; i--) {
    if (A[i] > max) max = A[i];
    top[i] = max;
}

所以你可以用二进制搜索快速找到它们:

int find(int[] t, int min) {
    int s = 0;
    int e = t.length-1;

    if (t[e] >= min) return e;

    while (true) {
        int x = (s+e) / 2;
        if (x == t.length-1) return t.length-1;
        if (t[x] >= min && t[x+1] < min) return x;

        if (t[x] < min) e = x;
        else s = x;
    }
}

你得到了一个解决方案:

int best = 0;
for (int i=0; i<A.length; i++) {
    int c = find(top, A[i]) - i;
    if (c > best) best = c;
    if (best >= A.length-i) return best;
}

return best;

答案 1 :(得分:1)

还有另一种算法,基于找到对之间的最大距离(抱歉,PHP),它还具有O(n2)复杂度:

function solution($a) {

    $length = count($a);

    for($max = $length-1; $max > 0; $max-- ) {
        for($i = 0; $i < $length - $max ; $i++) {
            if ($a[$i] <= $a[$i+$max]) {
                return $max;
            }    
        }
    }

    return 0;
}

答案 2 :(得分:0)

我认为你必须考虑距离。这就像广泛的第一次搜索。寻找具有最大距离(数组的大小)的所有夫妇,然后查找距离为1的那对夫妇,依此类推。我正在努力,并将尝试使用c ++解决方案。

答案 3 :(得分:0)

我遇到了类似的测试并选择在C中解决它。 我相信我的解决方案运行为O(nlog(n))最坏情况和O(1)最佳情况。 现在我松散地使用O(1),但它很可能。

基本上我用2个指针工作。一个从阵列的尾部缓慢移动,一个扫描从头部发现的每个。我立即从那些索引最远的对上的循环中断开,这恰好是使用这种方法首先计算的对。

O(1)成为可能,因为如果您计算的第一个单调对恰好位于列表的末尾和头部,那么这就是您的答案。没有可能的值大于此值。

int solution(int A[], int N) {
    // write your code in C90
    int p,q;
    // forward and backwards iterators
    int fi,bi=N-1;
    // track largest difference
    int diff=0;

    // interate through entire loop
    for(; bi >= 0; --bi){
       // Initialization
       p=q=bi;
       fi=0;

       // looking from the front
       for(fi=0; fi<bi; fi++){
          if(A[fi] <= A[p] && A[q] >= A[fi] && fi<bi){
             p=fi;
             break;
          }
       }
       if(diff < (q-p)){
          diff = (q-p);
       }

       if(diff >= bi){
          break;
       }
    }
    return diff;
}

答案 4 :(得分:0)

我的解决方案但得到了66%。其O(n ** 2)时间复杂度。代码是JavaScript。

function solution(A) {
    var N = A.length;
    var distance = 0;
    for(var i = 0; i < N-1; i++) {
        for(var j = i; j < N; j++){            
            if(A[i] <= A[j]  && (j - i) > distance)
                distance = j - i;
        }
    }
    return distance;
}