Given a string s, reverse all the words in s. The string is a bytearray and the words are separated by whitespace.
Input: 'Silence is peaceful'
Output: 'peaceful is Silence'
Input: 'Alice likes Bob'
Output: 'Bob likes Alice'
def reverse_words(s):
s[:] = s[::-1]
start = 0
while True:
end = s.find(b' ', start)
if end < 0:
if start == 0:
s[:] = s[::-1]
else:
s[start:] = s[end:start-1:-1]
break
if start < end:
if start == 0:
s[start:end] = s[end-1::-1]
else:
s[start:end] = s[end-1:start-1:-1]
start = end + 1
def reverse_words_pythonic(s):
s[:] = b' '.join(word[::-1] for word in s[::-1].split(b' '))
- The solution reverses the string, then uses two pointers to reverse each word in the reversed string, whose indices are determined by finding the index of each whitespace character
- This solution performs each operation in-place
- The pythonic solution uses list comprehension to generate a string with each word reversed in the reversed representation of the string
- This solution is technically not in-place, as using built-in functions like
str.split()
create a new object, though they are usually temporary objects with references to the original that do not take up much space - Despite the fact that the pythonic solution theoretically has a higher time/space complexity, it performs significantly faster than the in-place solution
- This solution is technically not in-place, as using built-in functions like
- Reverse the string
s[:] = s[::-1]
- Loop through the reversed string to reverse each word using a start and end pointer
start = 0 while True: end = s.find(b' ', start)
start
represents the start index of a wordend
represents the end index of a words.find(b' ', start)
returns the index of the first whitespace character after start
- Loop until we have reached the end of the string
if end < 0:
s.find(b' ', start)
will return -1 if no whitespace character is found
- When we reach the end of the string, be sure to reverse the last word before breaking out of the loop
if start == 0: s[:] = s[::-1] else: s[start:] = s[end:start-1:-1] break
if start == 0
is the case that the string is one word without any whitespace characters, so we simply reverse the entire string againelse
we need to reverse the last word in the string that occurs after a whitespace character
- Reverse each word in the string during the loop
if start < end: if start == 0: s[start:end] = s[end-1::-1] else: s[start:end] = s[end-1:start-1:-1] start = end + 1
if start < end
is the case that we are not at the last wordif start == 0
is the case that we are at the first wordelse
we are at a word between the first and last word in the stringstart = end + 1
moves the start pointer to the next character so that the loop can find the next whitespace character- Note that while Python slicing notation follows the syntax
a[start:stop:step]
, when using -1 to step backwards, it reverses the stop and start positions so that it follows the syntaxa[stop:start:-1]
- Use list comprehension and slice notation to reverse each word in the reversal of the string
Let's break this awesome line of code down:
s[:] = b' '.join(word[::-1] for word in s[::-1].split(b' '))
s[::-1].split(b' ')
returns a list of words in the reversal of the string with a whitespace character as the delimeterb' '
means we are defining the delimeter as a whitespace character in a bytearray object
word[::-1] for word in s[::-1]
reverses each word in the reversal of the stringb' '.join
joins each reversed word in the reversed list by a whitespace character to create the final string