我只是在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;
}
答案 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;
}