我有这个问题:
有一个N个元素的整数向量,我称之为A
然后有两个元素,我称之为(P,Q)
,因此0<= P <= Q <N
(P,Q
是A
的索引。)
我们使用这两个元素来计算L = A[P] + A[Q] + (Q-P)
。
我必须使用复杂度为O(n)且使用O(1)内存的算法计算L
的最大值。
这是我的解决方案,但我认为是O(n^2)
:
int L = 0;
for(int i=0; i<A.size(); i++) {
for(int j=i; j<A.size(); j++) {
L = max(L, A[i] +A[j] +(j-i) );
}
}
cout<<"Best: "<<L<<endl;
你有更好的算法来解决这个问题吗?
修改
这是一个简单的例子:
A = [-8,4,0,5,-3,6]
结果应为L = 14
( A[1] +A[5] +(5-1) )
最终解决方案
int solve_A_2_002(const std::vector<int>& A) {
int P = A[0];
int P_i = 0; //index
int Q = A[0];
int Q_i = 0;
int L = P+P;
int temp1,temp2, temp3;
for(int i=0; i<A.size(); i++) {
temp1 = A[i] + P + (i - P_i);
temp2 = A[i] + Q + (i - Q_i);
temp3 = A[i] + A[i];
if(L < temp1) {
L = temp1;
Q_i = i; //save new couple (P,Q)
Q = A[i];
}
if(L < temp2) {
L = temp2;
P_i = i;
P = A[i];
}
if(L < temp3) {
L = temp3;
P_i = Q_i = i;
Q = P = A[i];
}
}
return L;
}
答案 0 :(得分:3)
当您使用两个变量的所有组合执行某些操作但仍希望子二次时间时,常常要做的事情就是尝试将您所做的任何事情分成两部分< em> one -variable things。
在这种情况下,这很简单:
L = (A[P] - P) + (A[Q] + Q);
我们可以通过最大化两个部分来显着地在线性时间和恒定记忆中最大化这个数量。但我们可以明显解决的问题是一个简化问题:真正的问题有一个额外的约束P <= Q
。
一般来说,我们还需要做更多的工作来完成我们可以简单计算的事情并将它们结合起来以产生我们想要的问题的答案。有时这种进一步的分析可能有点复杂,或者需要一些巧妙的方法将我们可以轻松计算的事物组合成我们实际关心的问题的解决方案。
在这种情况下,我们可以轻松解决的简化问题的解决方案解决原始问题。一个简单的方法是写
A[x] - x = (A[x] + x) - 2x
从中可以很容易地看出,如果x=Q
是最大化A[x] + x
的值,那么制作x>Q
必须为A[x] - x
产生较小的值。
答案 1 :(得分:1)
无法真正证明它(而且已经很晚了),但算法应该将第一个元素作为P
和Q
,(P=0
,Q=0
),并迭代数组的其余部分,并为每个元素E
计算L
仅三对,(P, E)
,(Q, E)
和(E, E)
。如果其中一个大于旧(P, Q)
,则将该对作为新P
和Q
。