Given a wordthat contains lower or upper case characters, a starting index that indicates the starting position to begin a search in word, and a target character to find, return the minimum distance between that character at the indexto begin search, to the target character to find under the assumption that wordis a rotated string.
The Idea: First preprocess a distance array, which will provide us with the minimum distance to go from start to a target character within a rotated array. Next preprocess a dictionary that maps all the characters in word, with it's occurrences with the distance array. Note that these have to be sorted in order to later perform binary search. Finally, perform binary search on the list within the dictionary that contains all mappings for a the target character to search for. We know that we found the target word then the current middle element has a smaller distance to the target index, then both its left and right neighbors.
Complexity:O(N + log(N) + N^2log(N)) time. O(N) time for preprocessing the distance array, O(N+N^2Log(N)) for preprocessing the dictionary and sorting all the elements and finally O(logN) time for binary search. O(N) space for the distance array, and another O(N) space for the dictionary mapping, since at worse case, the characters scale linearly with their locations in the distance array.
defsortedCharLocationMap(word,indices):""" :param word: [string] target key mapping :param indices: List [int] target value mapping :return: dictionary [char]:[List[int]] """map= collections.defaultdict(list)for i, char inenumerate(word):map[char].append(indices[i])for key, locs inmap.items():map[key]=sorted(locs)returnmapdefmapRotatedDistances(word,start):""" :param word: [string] rotated word :param start: [int] relative to :return: List [int] """ distance_ar = [float('inf')for i inrange(0, len(word))] rev_it =1for i inrange(0, len(word)): actual = (i + start) %len(word) distance_ar[actual]=min(distance_ar[actual], i)for i inreversed(range(0, len(word))): actual = (i + start) %len(word) distance_ar[actual]=min(distance_ar[actual], rev_it) rev_it +=1return distance_ardefbinarySearchMinDist(dup_chars,left,right,key):if (left <= right): mid =int(left +abs(left - right) /2) mid_dist =abs(dup_chars[mid] - key)if mid +1<len(dup_chars)and mid -1>=0:ifabs(dup_chars[mid+1] - key)>= mid_dist \andabs(dup_chars[mid -1] - key)>= mid_dist:return dup_chars[mid]elif mid -1>=0and mid +1>=len(dup_chars):ifabs(dup_chars[mid-1] - key)>= mid_dist:return dup_chars[mid]elif mid +1<len(dup_chars)and mid -1<0:ifabs(dup_chars[mid+1] - key)>= mid_dist:return dup_chars[mid]elif mid +1>=len(dup_chars)and mid -1<0:return dup_chars[mid]if dup_chars[mid]> key:returnbinarySearchMinDist(dup_chars, left, mid-1, key)else:returnbinarySearchMinDist(dup_chars, mid+1, right, key)else:return-1defshortestRotatedDistance(word,start_i,search):""" :param word: [string] full word to search :param start_i: [int] index to start search :param search: [char] target search :return: [int] min distance """ distance_array =mapRotatedDistances(word, start_i) char_locs =sortedCharLocationMap(word, distance_array) dup_chars = char_locs[search] start_i = distance_array[start_i]returnbinarySearchMinDist(dup_chars, 0, len(dup_chars) -1, start_i)# find the minimum distance from index i to char c in wordprint(shortestRotatedDistance("godding", 0, 'g'))# 0print(shortestRotatedDistance("godding", 0, 'd'))# 2print(shortestRotatedDistance("godding", 1, 'n'))# 3print(shortestRotatedDistance("godding", 5, 'g'))# 1print("\n")print(shortestRotatedDistance("dadiedd", 0, 'a'))# 1print(shortestRotatedDistance("dadiedd", 3, 'd'))# 1print(shortestRotatedDistance("dadiedd", 2, 'e'))# 2print("\n")print(shortestRotatedDistance("ggggggg", 0, 'g'))# 0print(shortestRotatedDistance("ggggggg", 3, 'g'))# 0print(shortestRotatedDistance("ggggggg", 2, 'g'))# 0print("\n")print(shortestRotatedDistance("ggggggghhhhh", 7, 'g'))# 1print(shortestRotatedDistance("ggggggghhhhh", 0, 'h'))# 1print(shortestRotatedDistance("ggggggghhhhh", 1, 'h'))# 2print("\n")print(shortestRotatedDistance("ahahahahaha", 0, 'h'))# 1print(shortestRotatedDistance("ahahahahaha", 1, 'a'))# 1print(shortestRotatedDistance("ahahahahaha", 5, 'a'))# 1print("\n")