简体   繁体   中英

Next Word in Lexicographic Order

Problem

There is a word given. We need to find the next word occurring in lexicographic order.For example, if word is lkjihfg then the next word would be lkjihgf .

This is a problem at Hackerrank that you can see here . The problem for reference:

Complete the biggerIsGreater function in the editor below. It should return the smallest lexicographically higher string possible from the given string or no answer.

My effort

What i've tried was finding the maximum index(say indx ) of word such that after it all the characters are non increasing.Then swapping the char at indx with the minimum char ahead that is greater than char at indx . Finally, reversing the string after indx .

Code

def biggerIsGreater(w):
    ww = list(set(w))
    indx = -1
    l = [ord(ch)for ch in w]
    for i in range(len(l)-1):
        if l[i] < l[i+1]:
            indx = i
        else:
            continue
    if indx == -1:
        return "no answer"
    j = len(l) - 1
    for x in range(j,indx,-1):
        if l[x] > l[indx]:
            l[x], l[indx] = l[indx], l[x]
            break
    l[indx+1 : ] = l[len(l) - 1 : indx : -1]
    y = []
    for z in l:
        y.append(chr(z))
    ans = ''.join(y)
    return ans

The problem with this code is that it's not passing all the test cases because it's producing wrong results.

The good thing about your solution is that it has a good time complexity - O(n) , where n is a size of the input string. That's why you don't have any timeout errors.

The problem with this code is, however is not all the test cases are validating.

That's so because you've missed one important case in your loop below:

for x in range(j,indx,-1):
    if l[x] >= l[indx]:
        l[x], l[indx] = l[indx], l[x]
        break

Consider a case like 5 4 6 4 . So, your indx is 2 and because of your condition l[x] >= l[indx] you will replace l[2] = 4 with l[0] = 4 . This way, your next word in lexicographical order won't change and you'll get a wrong result 5 4 4 6 even though it must be 5 6 4 4 .

So, if you make your condition stricter > and not >= because you actually need a LARGER character from the left then the solution will be working correctly.

Hence, just change your condition to > :

for x in range(j,indx,-1):
    if l[x] > l[indx]: # fix the sign here
        l[x], l[indx] = l[indx], l[x]
        break

I tested your code with the fix and it passed all the tests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM