0

how to find the index in an circular array such that the string that is formed starting from that index is first in lexicographic order.

For Ex : in the circular array ABCDEABCCDE The answer is 6 because the circular string starting from the element A in the 6th position comes first in the dictionary formed from all the possible strings of the circular array.

jairaj
  • 1,789
  • 5
  • 19
  • 32
  • You can find it quite easily: generate all possible strings (there will be `n` of them, where `n` is the length of the original string), then simply find the first one using linear search/selection. Both operations take `O(n)` time. –  Aug 10 '13 at 21:57
  • @H2CO3 : the complexity will be very larger. I am looking for O(n) algorithm. Your approach is O(n^2). – jairaj Aug 10 '13 at 22:04
  • @jairaj "Very larger"? Why would it? It takes `O(n)` to generate the substrings, then `O(n)` to search for the minimum. (And anyway, now are yoyu looking for an `O(n)` or an `O(1)` solution? Your comment doesn't match the criterion in the title.) –  Aug 10 '13 at 22:10
  • @H2CO3 If you're not careful, it would take `O(n)` to generate a substring of length `n`, and hence `O(n^2)` to generate them all. – Teepeemm Aug 10 '13 at 22:14
  • @Teepeemm Aham, you're talking about the naive approach! I see :) Well, I like in-place string manipulation. I wouldn't **actually** generate substrings, starting the min search from the `k`th character seems less complex. –  Aug 10 '13 at 22:16
  • @H2CO3 sorry i meant O(n).Edited it. – jairaj Aug 10 '13 at 22:16
  • And it is not substring. The entire string is circular and we have to look at the complete string starting from a particular index and then again from the start to the index. "Circular". – jairaj Aug 10 '13 at 22:18
  • 1
    @H2CO3: How exactly do you use "linear search/selection" to find the lexicographically minimal string? Unless you use special tricks, you need to make at least n-1 comparisons (think Tournament selection), each of which can take O(n) time. – j_random_hacker Aug 11 '13 at 00:04

2 Answers2

0

Theory A: If there are K occurrences of a letter X in a sequence of length N, there are at least two occurrences of X such that the distance between them is less than N/K.

Find the min letter and arrange pointers to all of its occurrences in a sorted list. Call it A.

For a given r, find min of letters at A[i]+r, and filter out all the pointers for which element at A[i]+r is not equal to min. Also filter out all the pointers A[j] such that A[j]=A[i]+r for some i.

You will have to run the above statement at most N/K times and each run would cost at most O(K) time. Therefore, the complexity of this algorithm is O(N).

More detailed algorithm: Assume Z is the circular list we are dealing with.

def filter(A,Z,r):
    t = min( Z[A[i]+r] ) forall i
    remove A[i] if Z[A[i]+r]!=t forall i

    rmflag = [false if A[i]==A[j]+r else false for i in range(len(A)] //NOTE: This step can be done in O(len(A)) time since A is sorted
    remove A[i] if rmflag[i]
ElKamina
  • 7,747
  • 28
  • 43
-1
Step 1: find the min char, call it minChar
Step 2: build list L0 = {i: string[i] == minChar, but string[i-1] != minChar}
Step 3: if L0.size() == 1, return L0[0]
step 3:
        3.0 set k=0, let L = L0
        3.1 k++
        3.2 BUild L1 = {i+1, i in L}. Build L = {i: string[i] is smallest for any k in L1}
        3.3 If L.size() == 1, return L[0]-k. Otherwise goto 3.1 to repeat

This should give you an O(n) expected complexity.

ElKamina
  • 7,747
  • 28
  • 43
  • I think your solution fails for case like ABABABABABABABABABABAD (in which case the solution will be O(n^2)) – ElKamina Aug 11 '13 at 04:00