Reputation: 9791
I have a problem where I need to find the maximum distance between two different elements in an array.
For example: given an array 4,6,2,2,6,6,4
, the method should return 5
as the max distance.
I am able to solve the problem using two for loops but it is not an optimized solution. Am trying to optimize it by doing it in a single for loop.
here is my current solution:
int [] A = {4,6,2,2,6,6,4};
int N = A.length;
int result = 0;
for (int i = 0; i < N; i++){
for (int j = i; j < N; j++) {
if(A[i] != A[j]){
result = Math.max(result, j - i);
}
}
}
// tried below code but it is not efficient
// for (int i = 0; i < N; i++){
//
// if(A[N-1] != A[i]){
// result = Math.max(result, N-1-i);
// }
// }
System.out.println(result);
How to make this better in terms of time complexity?
Upvotes: 6
Views: 9482
Reputation: 186688
Simple (not nested) loop is enough, but two cases should be taken into account: either the best result is
4,6,2,2,6,6,4
^ ^ - moving first
or
4,6,2,2,6,6,4
^ ^ - moving last
for instance: [4, 2, 4, 4, 4]
moving first brings the answer, when in case of [4, 4, 4, 2, 4]
moving last should be used.
int first = 0;
int last = A.length - 1;
// 1st case: moving "first"
while (first < last) {
if (A[first] == A[last])
first++;
else
break;
}
int diff1 = last - first;
first = 0;
last = A.length - 1;
// 2nd case: moving "last"
while (first < last) {
if (A[first] == A[last])
last--;
else
break;
}
int diff2 = last - first;
// result is the max between two cases
int result = diff1 > diff2
? diff1
: diff2;
So we have O(N)
time complexity.
Edit: Let's proof that at least one of the indexes is either 0
or length - 1
. Let's do it by contradiction. Suppose we have a solution like
a, b, c, .... d, e, f, g
^ ..... ^ <- solution indexes (no borders)
Items to the left of c
must be d
, otherwise we can take a
or b
indexes and have an improved solution. Items to right of d
must be c
or we can once again push last index to the right and have a better solution. So we have
d, d, c .... d, c, c, c
^ .... ^ <- solution indexes
Now, since d <> c
(c..d
is a solution) we can improve the solution into
d, d, c .... d, c, c, c
^ .... ^ <- solution indexes
^ .... ^ <- better solution
We have a contradiction (the supposed solution is not one - we have a better choice) and that's why at least one index must be 0
or length - 1
.
Now we have 2 scenarions to test:
a, b, ..... y, z
^ ...... ^ <- moving first
^ ...... ^ <- moving last
We can combine both conditions into if
and have just one loop:
int result = 0;
for (int i = 0; i < A.length; ++i)
if (A[i] != A[A.length - 1] || A[0] != A[A.length - 1 - i]) {
result = A.length - i - 1;
break;
}
Upvotes: 8
Reputation: 1621
This can be done in a single loop
Consider this.
The maximum difference between from a index i
can be either between start element and i
or i
and the last element
int main() {
vector<int> v {4, 6, 2, 2, 6, 6, 4};
int start = 0, end = v.size() -1;
int result = 0;
for(int i=0; i< v.size(); ++i)
{
if(v[i] != v[start])
{
result = max(result, i);
}
if(v[i] != v[end])
{
result = max(result, end - i);
}
}
return result;
}
The reason we are able to achieve a O(N)
algorithm is because
Consider v = [4, 4, 2, 3, 4, 4]
At index i = 0
we check if we can find the maximum possible distance i.e with the last element but since they are same we can't consider it.
At i = 0
for this array the maximum possible answer would have been 5.
[4, 4, 2, 3, 4, 4]
^
At i = 1
we again check both ends of the array still the same so we move on.
The real savings come here that we do not have to check for every other entry
keeping the start at i = 0
So, at i = 2
, we find that the maximum can be obtained with the end of the array
[4, 4, 2, 3, 4, 4]
^ ^ ^
start i end
which is the same as keeping the start
constant and keeping a runner loop.
Upvotes: 3