You are given a 0-indexed circular string array words and a string target. A circular array means that the array's end connects to the array's beginning.
words[i] is words[(i + 1) % n] and the previous element of words[i] is words[(i - 1 + n) % n], where n is the length of words.Starting from startIndex, you can move to either the next word or the previous word with 1 step at a time.
Return the shortest distance needed to reach the string target. If the string target does not exist in words, return -1.
Example 1:
Input: words = ["hello","i","am","leetcode","hello"], target = "hello", startIndex = 1 Output: 1 Explanation: We start from index 1 and can reach "hello" by - moving 3 units to the right to reach index 4. - moving 2 units to the left to reach index 4. - moving 4 units to the right to reach index 0. - moving 1 unit to the left to reach index 0. The shortest distance to reach "hello" is 1.
Example 2:
Input: words = ["a","b","leetcode"], target = "leetcode", startIndex = 0 Output: 1 Explanation: We start from index 0 and can reach "leetcode" by - moving 2 units to the right to reach index 3. - moving 1 unit to the left to reach index 3. The shortest distance to reach "leetcode" is 1.
Example 3:
Input: words = ["i","eat","leetcode"], target = "ate", startIndex = 0
Output: -1
Explanation: Since "ate" does not exist in words, we return -1.
Constraints:
1 <= words.length <= 1001 <= words[i].length <= 100words[i] and target consist of only lowercase English letters.0 <= startIndex < words.lengthWhen you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force way to find the shortest distance involves checking every possible starting point in the word list and then looking in both directions around the circle. We continue doing this until we find the target word. We then remember the shortest trip we had to take.
Here's how the algorithm would work step-by-step:
def shortest_distance_brute_force(circular_array, target_word):
array_length = len(circular_array)
shortest_distances = []
for start_index in range(array_length):
# Iterate through each word in the array as a starting point.
for direction in [-1, 1]: # Check both directions
current_distance = 0
current_index = start_index
while True:
if circular_array[current_index] == target_word:
shortest_distances.append(current_distance)
break #Target found, break inner loop
current_distance += 1
current_index = (current_index + direction) % array_length
# Avoid infinite loops if target not found.
if current_distance >= array_length:
break
# Avoid returning min of empty list
if not shortest_distances:
return -1
return min(shortest_distances)The key to efficiently solving this problem lies in realizing that we only need to consider two possible directions to find the target word from the starting word. We can calculate the distance in both directions and choose the shorter one. This avoids checking every single position in the array.
Here's how the algorithm would work step-by-step:
def shortest_distance(word_list, start_word, target_word):
list_length = len(word_list)
start_index = -1
for i in range(list_length):
if word_list[i] == start_word:
start_index = i
break
if start_index == -1:
return -1
forward_distance = 0
backward_distance = 0
forward_index = start_index
backward_index = start_index
# Find the forward distance to the target word.
while forward_distance < list_length:
if word_list[forward_index] == target_word:
break
forward_index = (forward_index + 1) % list_length
forward_distance += 1
# Find the backward distance to the target word.
while backward_distance < list_length:
if word_list[backward_index] == target_word:
break
backward_index = (backward_index - 1 + list_length) % list_length
backward_distance += 1
# Check if the target word exists in the list
if forward_distance == list_length and backward_distance == list_length:
return -1
# Compare forward and backward distances to determine the shortest path.
return min(forward_distance, backward_distance)| Case | How to Handle |
|---|---|
| words array is null or empty | Return an empty array or an array filled with -1 (or a similar sentinel value) to indicate no solution since no words exist. |
| target string is null or empty | Return an array filled with the length of the words array, as no target exists and thus every word is effectively maximally distant. |
| words array contains only one element | If the single element matches the target, return [0]; otherwise return [1]. |
| target string does not exist in the words array | Return an array filled with the length of the `words` array, indicating maximum possible distance for each element. |
| target string appears multiple times in the words array | The solution should find the minimum distance among all occurrences of the target. |
| words array contains very long strings | String comparison needs to be efficient, and consider possible memory consumption if strings are extremely long but doesn't fundamentally change the distance calculation. |
| words array has a large number of words (e.g., exceeding memory constraints). | Consider optimizing for memory by iterating through the array and calculating the shortest distances on-the-fly instead of storing all target indices beforehand, and if absolutely necessary break up the large array into manageable chunks. |
| words array contains duplicate strings, and the target is one of them. | The algorithm should correctly calculate distances to all occurrences, even if some are at the same string value but distinct positions. |