Reputation: 6364
It is an interesting puzzle I came across , according to which , given an array , we need to find the ninja index in it.
A Ninja index is defined by these rules :
An index K such that all elements with smaller indexes have values lower or equal to A[K] and all elements with greater indexes have values greater or equal to A[K].
For example , consider :
A[0]=4, A[1]=2, A[2]=2, A[3]=3, A[4]=1, A[5]=4, A[6]=7, A[7]=8, A[8]=6, A[9]=9.
In this case, 5
is a ninja index , since A[r]<=A[5] for r = [0,k] and A[5]<=A[r] r = [k,n].
What algorithm shall we follow to find it in O(n) . I already have a brute force O(n^2) solution.
EDIT : There can be more than 1 ninja index , but we need to find the first one preferably. And in case there is no NI , then we shall return -1.
Upvotes: 8
Views: 465
Reputation: 82929
Another Python solution, following the same general approach. Maybe a bit shorter.
def ninja(lst):
maxs = lst[::]
mins = lst[::]
for i in range(1, len(lst)):
maxs[ i] = max(maxs[ i], maxs[ i-1])
mins[-1-i] = min(mins[-1-i], mins[-i ])
return [i for i in range(len(lst)) if maxs[i] <= lst[i] <= mins[i]]
I guess it could be optimized a bit w.r.t that list-copying-action, but this way it's more concise.
Upvotes: 2
Reputation: 12006
This straight-forward Java code calculates leftmost index that has property "all elements rightwards are not lesser":
private static int fwd(int[] a) {
int i = -1;
for (int j = 0; j < a.length - 1; j++) {
if (a[j + 1] >= a[j] && i == -1) {
i = j + 1;
} else if (i != -1 && a[j + 1] < a[i]) {
i = -1;
}
}
return i;
}
Almost same code calculates leftmost index that has property "all elements leftwards are not greater":
private static int bwd(int[] a) {
int i = -1;
for (int j = 0; j < a.length - 1; j++) {
if (a[j + 1] >= a[j] && i == -1) {
i = j + 1;
} else if (i != -1 && a[j + 1] < a[i]) {
i = -1;
}
}
return i;
}
If results are the same, leftmost Ninja index is found.
Upvotes: 0
Reputation: 21
A python solution that will take O(3n) operations
def n_index1(a):
max_i = []
maxx = a[0]
for j in range(len(a)):
i=a[j]
if maxx<=i and j!=0:
maxx=i
max_i.append(1)
else:
max_i.append(-1)
return max_i
def n_index2(a):
max_i = []
maxx = -a[len(a)-1]
for j in range(len(a)-1,-1,-1):
i=-a[j] # mind the minus
if maxx<=i and j!=len(a)-1:
maxx=i
max_i.append(1)
else:
max_i.append(-1)
return max_i
def parse_both(a,b):
for i in range(len(a)):
if a[i]==1 and b[len(b)-1-i]==1:
return i
return -1
def ninja_index(v):
a = n_index1(v)
b = n_index2(v)
return parse_both(a,b)
Upvotes: 2
Reputation: 45131
Precompute minimum values for all the suffixes of the array and maximum values for all prefixes. With this data every element can be checked for Ninja in O(1).
Upvotes: 8