There is a leetcode question on recursion. Reverse a string, in place, using recursion. Do not allocate an additional array.
Write a function that reverses a string. The input string is given as
an array of characters char[].
Do not allocate extra space for another array, you must do this by
modifying the input array in-place with O(1) extra memory.
You may assume all the characters consist of printable ASCII
characters.
My solution doesn't work as my slicing operator is creating a copy of the list, rather than being in place. I can't seem to add a parameter to the function, as the test harness isn't expecting an additional parameter.
How do you do this, without an additional parameter to detect the current position index into the string you are trying to reverse, or without an intermediate data structure you append to through the recursive call?
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if len(s) <= 1:
return
temp = s[0]
s[0] = s[len(s)-1]
s[len(s)-1] = temp
return self.reverseString(s[1:len(s)-1])
My function with an input of "hello" returns ["o","e","l","l","h"]. This is because the first time the function is called it operates on the list in place, and subsequent calls are achieved through a slice of the string.
From what i understood, the solution should be recursive. Try this:
EDIT: (as should look in leetcode)
def reverseStringHelper(s, index):
length = len(s)
if index >= length / 2:
return
temp = s[index]
s[index] = s[length - 1 - index]
s[length - 1 - index] = temp
reverseString(s, index + 1)
def reverseString(s):
reverseStringHelper(s, 0)
Defining arr = ['h', 'e', 'l', 'l' ,'o'] and calling reverseString(arr, 0) will result in ['o', 'l', 'l', 'e', 'h']
You may call it from a different function so it would only accept the list.
Thanks all. The solution was to add a parameter with a default, to get over the issues with the leetcode test harness, so now I can do it as below:
class Solution:
def reverseString(self, s: List[str], start = 0) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if len(s[start:len(s)-start]) <= 1:
return
end = len(s) - start - 1 # end postition
temp = s[start]
s[start] = s[end]
s[end] = temp
self.reverseString(s, start+1)
Try this
chars=list('string')
for i in range((len(chars)-len(chars)%2)//2):
chars[i], chars[-i-1]=chars[-i-1], chars[i]
print(chars)
print(''.join(chars))
This'll pass, since it has to be done in-place:
from typing import List
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
left, right = 0, len(s) - 1
while left < right:
s[left], s[right] = s[right], s[left]
left, right = left + 1, right - 1
References
For additional details, please see the Discussion Board where you can find plenty of well-explained accepted solutions with a variety of languages including low-complexity algorithms and asymptotic runtime/memory analysis1, 2.
Related
I want to use recursion to reverse a string in python so it displays the characters backwards (i.e "Hello" will become "olleh"/"o l l e h".
I wrote one that does it iteratively:
def Reverse( s ):
result = ""
n = 0
start = 0
while ( s[n:] != "" ):
while ( s[n:] != "" and s[n] != ' ' ):
n = n + 1
result = s[ start: n ] + " " + result
start = n
return result
But how exactly do I do this recursively? I am confused on this part, especially because I don't work with python and recursion much.
Any help would be appreciated.
def rreverse(s):
if s == "":
return s
else:
return rreverse(s[1:]) + s[0]
(Very few people do heavy recursive processing in Python, the language wasn't designed for it.)
To solve a problem recursively, find a trivial case that is easy to solve, and figure out how to get to that trivial case by breaking the problem down into simpler and simpler versions of itself.
What is the first thing you do in reversing a string? Literally the first thing? You get the last character of the string, right?
So the reverse of a string is the last character, followed by the reverse of everything but the last character, which is where the recursion comes in. The last character of a string can be written as x[-1] while everything but the last character is x[:-1].
Now, how do you "bottom out"? That is, what is the trivial case you can solve without recursion? One answer is the one-character string, which is the same forward and reversed. So if you get a one-character string, you are done.
But the empty string is even more trivial, and someone might actually pass that in to your function, so we should probably use that instead. A one-character string can, after all, also be broken down into the last character and everything but the last character; it's just that everything but the last character is the empty string. So if we handle the empty string by just returning it, we're set.
Put it all together and you get:
def backward(text):
if text == "":
return text
else:
return text[-1] + backward(text[:-1])
Or in one line:
backward = lambda t: t[-1] + backward(t[:-1]) if t else t
As others have pointed out, this is not the way you would usually do this in Python. An iterative solution is going to be faster, and using slicing to do it is going to be faster still.
Additionally, Python imposes a limit on stack size, and there's no tail call optimization, so a recursive solution would be limited to reversing strings of only about a thousand characters. You can increase Python's stack size, but there would still be a fixed limit, while other solutions can always handle a string of any length.
I just want to add some explanations based on Fred Foo's answer.
Let's say we have a string called 'abc', and we want to return its reverse which should be 'cba'.
def reverse(s):
if s == "":
return s
else:
return reverse(s[1:]) + s[0]
s = "abc"
print (reverse(s))
How this code works is that:
when we call the function
reverse('abc') #s = abc
=reverse('bc') + 'a' #s[1:] = bc s[0] = a
=reverse('c') + 'b' + 'a' #s[1:] = c s[0] = a
=reverse('') + 'c' + 'b' + 'a'
='cba'
If this isn't just a homework question and you're actually trying to reverse a string for some greater goal, just do s[::-1].
def reverse_string(s):
if s: return s[-1] + reverse_string(s[0:-1])
else: return s
or
def reverse_string(s):
return s[-1] + reverse_string(s[0:-1]) if s else s
I know it's too late to answer original question and there are multiple better ways which are answered here already. My answer is for documentation purpose in case someone is trying to implement tail recursion for string reversal.
def tail_rev(in_string,rev_string):
if in_string=='':
return rev_string
else:
rev_string+=in_string[-1]
return tail_rev(in_string[:-1],rev_string)
in_string=input("Enter String: ")
rev_string=tail_rev(in_string,'')
print(f"Reverse of {in_string} is {rev_string}")
s = input("Enter your string: ")
def rev(s):
if len(s) == 1:
print(s[0])
exit()
else:
#print the last char in string
#end="" prints all chars in string on same line
print(s[-1], end="")
"""Next line replaces whole string with same
string, but with 1 char less"""
return rev(s.replace(s, s[:-1]))
rev(s)
if you do not want to return response than you can use this solution. This question is part of LeetCode.
class Solution:
i = 0
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if self.i >= (len(s)//2):
return
s[self.i], s[len(s)-self.i-1] = s[len(s)-self.i-1], s[self.i]
self.i += 1
self.reverseString(s)
I am trying to pass a parameter "by value". I have tried making a deep copy of the parameter that is passed recursively in order to prevent any changes from circling back to the parent function calls.
Here is a snippet of code that tries to generate the array of all possible parentheses.
def generateParenthesis(n):
#Iterate for each move.
M = 2 * n
retArray = []
def recHelper(numMoves, perm, stack):
print("Function call: ", numMoves, perm, stack)
newPerm = copy.deepcopy(perm)
newStack = stack.copy()
#Base case, no moves
if (numMoves == 0):
retArray.append(newPerm)
return
#Case when left move is valid
if (numMoves != len(newStack)):
#Apply the left move. Pass it recursively
newPerm +='('
#Update the stack accordingly
newStack.append('(')
#Decrease numMoves
newNumMoves = numMoves - 1
#Call it recursively
recHelper(newNumMoves, newPerm, newStack)
#Case when right move is valid
if len(newStack) != 0:
#Apply the right move. Pass it recursively
newPerm +=')'
#Update the stack accordingly, delete the top, last elm
newStack.pop()
#Decrease numMoves
newNumMoves = numMoves - 1
#Call it recursively
recHelper(newNumMoves, newPerm, newStack)
#done
return
recHelper(M, "", [])
return retArray
Unfortunately, calling generateParenthesis(1) returns ['()','()(', '()()'] and not ['()'].
def generateParenthesis(n):
retArray = []
def append_solutions(partial, opened_p, closed_p):
if opened_p < n:
append_solutions(partial + '(', opened_p + 1, closed_p)
if closed_p < n and opened_p > closed_p:
append_solutions(partial + ')', opened_p, closed_p + 1)
if opened_p == closed_p == n and partial:
retArray.append(partial)
append_solutions('', 0, 0)
return retArray
print(generateParenthesis(1))
print(generateParenthesis(2))
print(generateParenthesis(3))
print(generateParenthesis(4))
print(generateParenthesis(5))
After 3 hours of simplifying ideas, I came with this working code.
Now it finds things like (()())() for generateParenthesis(4), for instance.
The code is very self explanatory. You keep a count of opened/closed parenthesis and only close parenthesis when there are correspondent opened.
I chose not to use a stack because since everything in Python is passed by "pointer copy", stacks (i.e. lists in your OP) would require a costly list(stack) in the function body, creating a local copy of the list.
Notice that I create new strings (partial + '(', for instance), and these new string objects are passed by "pointer copy" to recursion calls.
(Sorry I lack a better term now. But this is important)
Edit
Your solution has a problem with the variable newPerm. Its value is leaking into the second recursive function. Also, you need to understand that all your copying of values is not needed except for the stack.
See how your function can be simplified. I think it's working:
def generateParenthesisOP(n):
#Iterate for each move.
M = 2 * n
retArray = []
def recHelper(numMoves, perm, stack):
print("Function call: ", numMoves, perm, stack)
if numMoves == 0:
retArray.append(perm)
return
if numMoves != len(stack):
left_stack = list(stack)
left_stack.append('(')
recHelper(numMoves - 1, perm + '(', left_stack)
if len(stack) != 0:
right_stack = list(stack)
right_stack.pop()
recHelper(numMoves - 1, perm + ')', right_stack)
recHelper(M, "", [])
return retArray
Use + operator to add to a list rather than .append() behavior to best emulate pass by value behavior.
Python officially abides by pass-by-object-reference. In your case, when a list stack or perm passed and modified in the child function, the parent function's stack or perm will see the updated variable.
This exercise involves a codeacademy problem to write a function which takes a string as an input and outputs the string in reverse, I've found solutions as to how to do it online, I'm just confused as to why mine doesnt work:
def reverse(c):
empty=[]
stringsize= len(c)
for x in range(stringsize):
empty[x]=c[stringsize-x]
return empty
You need to start at indexing your string from -1 through to -stringsize, and use empty.append() to add values:
for x in range(stringsize):
empty.append(c[stringsize - x - 1])
Python indexing starts at 0, making stringsize - 1 the last index. Because empty is an empty list, you cannot index into it. Using the list.append() method adds new values at the end instead.
You don't really need the stringsize reference there, because negative indices automatically are subtracted from the length for you:
for x in range(len(c)):
empty.append(c[-x-1])
Since this is supposed to return a string, not a list, you need to join the characters again at the end:
return ''.join(empty)
The easiest way to reverse a list is to use a negative slice stride:
def reverse(c):
return c[::-1]
One solution :
def reverse(c):
empty=[]
stringsize= len(c)
for x in range(stringsize):
empty.append(c[-(x+1)])
return ''.join(empty)
print reverse('string')
Another:
def reverse(c):
empty=[]
stringsize= len(c)
for x in range(stringsize):
empty.append(c[stringsize - (x+1)])
return ''.join(empty)
print reverse('string')
Using recursion:
def reverse(string,start,stop):
if start < stop - 1:
string[start],string[stop - 1] = string[stop - 1],string[start]
reverse(string,start+1, stop-1)
return ''.join(string)
print reverse(list('string'), 0, len('string'))
In Python a string is an iterable so iterable functions can be used with it. For example reversed function:
>>> "".join(reversed("123"))
'321'
The least changes necessary to make your code run seem to be:
def reverse(c):
stringsize= len(c)
empty=[None] * stringsize
for x in range(stringsize):
empty[x]=c[stringsize-x-1]
return empty
But you should reconsider your name empty (as Martijn pointed out) because that thing isn't empty (at least in the end), so the name is misleading.
The classic answer to this problem is to use a slice with a negative step to get what you want:
def reverse(c):
return c[::-1]
...but maybe that's not allowed for you?
I understand that recursion is when a function calls itself, however I can't figure out how exactly to get my function to call it self to get the desired results. I need to simply count the vowels in the string given to the function.
def recVowelCount(s):
'return the number of vowels in s using a recursive computation'
vowelcount = 0
vowels = "aEiou".lower()
if s[0] in vowels:
vowelcount += 1
else:
???
I came up with this in the end, thanks to some insight from here.
def recVowelCount(s):
'return the number of vowels in s using a recursive computation'
vowels = "aeiouAEIOU"
if s == "":
return 0
elif s[0] in vowels:
return 1 + recVowelCount(s[1:])
else:
return 0 + recVowelCount(s[1:])
Try this, it's a simple solution:
def recVowelCount(s):
if not s:
return 0
return (1 if s[0] in 'aeiouAEIOU' else 0) + recVowelCount(s[1:])
It takes into account the case when the vowels are in either uppercase or lowercase. It might not be the most efficient way to traverse recursively a string (because each recursive call creates a new sliced string) but it's easy to understand:
Base case: if the string is empty, then it has zero vowels.
Recursive step: if the first character is a vowel add 1 to the solution, otherwise add 0. Either way, advance the recursion by removing the first character and continue traversing the rest of the string.
The second step will eventually reduce the string to zero length, therefore ending the recursion. Alternatively, the same procedure can be implemented using tail recursion - not that it makes any difference regarding performance, given that CPython doesn't implement tail recursion elimination.
def recVowelCount(s):
def loop(s, acc):
if not s:
return acc
return loop(s[1:], (1 if s[0] in 'aeiouAEIOU' else 0) + acc)
loop(s, 0)
Just for fun, if we remove the restriction that the solution has to be recursive, this is how I'd solve it:
def iterVowelCount(s):
vowels = frozenset('aeiouAEIOU')
return sum(1 for c in s if c in vowels)
Anyway this works:
recVowelCount('murcielago')
> 5
iterVowelCount('murcielago')
> 5
Your function probably needs to look generally like this:
if the string is empty, return 0.
if the string isn't empty and the first character is a vowel, return 1 + the result of a recursive call on the rest of the string
if the string isn't empty and the first character is not a vowel, return the result of a recursive call on the rest of the string.
Use slice to remove 1st character and test the others. You don't need an else block because you need to call the function for every case. If you put it in else block, then it will not be called, when your last character is vowel: -
### Improved Code
def recVowelCount(s):
'return the number of vowels in s using a recursive computation'
vowel_count = 0
# You should also declare your `vowels` string as class variable
vowels = "aEiou".lower()
if not s:
return 0
if s[0] in vowels:
return 1 + recVowelCount(s[1:])
return recVowelCount(s[1:])
# Invoke the function
print recVowelCount("rohit") # Prints 2
This will call your recursive function with new string with 1st character sliced.
this is the straightforward approach:
VOWELS = 'aeiouAEIOU'
def count_vowels(s):
if not s:
return 0
elif s[0] in VOWELS:
return 1 + count_vowels(s[1:])
else:
return 0 + count_vowels(s[1:])
here is the same with less code:
def count_vowels_short(s):
if not s:
return 0
return int(s[0] in VOWELS) + count_vowels_short(s[1:])
here is another one:
def count_vowels_tailrecursion(s, count=0):
return count if not s else count_vowels_tailrecursion(s[1:], count + int(s[0] in VOWELS))
Unfortunately, this will fail for long strings.
>>> medium_sized_string = str(range(1000))
>>> count_vowels(medium_sized_string)
...
RuntimeError: maximum recursion depth exceeded while calling a Python object
if this is something of interest, look at this blog article.
Here's a functional programming approach for you to study:
map_ = lambda func, lst: [func(lst[0])] + map_(func, lst[1:]) if lst else []
reduce_ = lambda func, lst, init: reduce_(func, lst[1:], func(init, lst[0])) if lst else init
add = lambda x, y: int(x) + int(y)
is_vowel = lambda a: a in 'aeiou'
s = 'How razorback-jumping frogs can level six piqued gymnasts!'
num_vowels = reduce_(add, map_(is_vowel, s), 0)
The idea is to divide the problem into two steps, where the first ("map") converts the data into another form (a letter -> 0/1) and the second ("reduce") collects converted items into one single value (the sum of 1's).
References:
http://en.wikipedia.org/wiki/Map_(higher-order_function)
http://en.wikipedia.org/wiki/Reduce_(higher-order_function)
http://en.wikipedia.org/wiki/MapReduce
Another, more advanced solution is to convert the problem into tail recursive and use a trampoline to eliminate the recursive call:
def count_vowels(s):
f = lambda s, n: lambda: f(s[1:], n + (s[0] in 'aeiou')) if s else n
t = f(s, 0)
while callable(t): t = t()
return t
Note that unlike naive solutions this one can work with very long strings without causing "recursion depth exceeded" errors.
I want to use recursion to reverse a string in python so it displays the characters backwards (i.e "Hello" will become "olleh"/"o l l e h".
I wrote one that does it iteratively:
def Reverse( s ):
result = ""
n = 0
start = 0
while ( s[n:] != "" ):
while ( s[n:] != "" and s[n] != ' ' ):
n = n + 1
result = s[ start: n ] + " " + result
start = n
return result
But how exactly do I do this recursively? I am confused on this part, especially because I don't work with python and recursion much.
Any help would be appreciated.
def rreverse(s):
if s == "":
return s
else:
return rreverse(s[1:]) + s[0]
(Very few people do heavy recursive processing in Python, the language wasn't designed for it.)
To solve a problem recursively, find a trivial case that is easy to solve, and figure out how to get to that trivial case by breaking the problem down into simpler and simpler versions of itself.
What is the first thing you do in reversing a string? Literally the first thing? You get the last character of the string, right?
So the reverse of a string is the last character, followed by the reverse of everything but the last character, which is where the recursion comes in. The last character of a string can be written as x[-1] while everything but the last character is x[:-1].
Now, how do you "bottom out"? That is, what is the trivial case you can solve without recursion? One answer is the one-character string, which is the same forward and reversed. So if you get a one-character string, you are done.
But the empty string is even more trivial, and someone might actually pass that in to your function, so we should probably use that instead. A one-character string can, after all, also be broken down into the last character and everything but the last character; it's just that everything but the last character is the empty string. So if we handle the empty string by just returning it, we're set.
Put it all together and you get:
def backward(text):
if text == "":
return text
else:
return text[-1] + backward(text[:-1])
Or in one line:
backward = lambda t: t[-1] + backward(t[:-1]) if t else t
As others have pointed out, this is not the way you would usually do this in Python. An iterative solution is going to be faster, and using slicing to do it is going to be faster still.
Additionally, Python imposes a limit on stack size, and there's no tail call optimization, so a recursive solution would be limited to reversing strings of only about a thousand characters. You can increase Python's stack size, but there would still be a fixed limit, while other solutions can always handle a string of any length.
I just want to add some explanations based on Fred Foo's answer.
Let's say we have a string called 'abc', and we want to return its reverse which should be 'cba'.
def reverse(s):
if s == "":
return s
else:
return reverse(s[1:]) + s[0]
s = "abc"
print (reverse(s))
How this code works is that:
when we call the function
reverse('abc') #s = abc
=reverse('bc') + 'a' #s[1:] = bc s[0] = a
=reverse('c') + 'b' + 'a' #s[1:] = c s[0] = a
=reverse('') + 'c' + 'b' + 'a'
='cba'
If this isn't just a homework question and you're actually trying to reverse a string for some greater goal, just do s[::-1].
def reverse_string(s):
if s: return s[-1] + reverse_string(s[0:-1])
else: return s
or
def reverse_string(s):
return s[-1] + reverse_string(s[0:-1]) if s else s
I know it's too late to answer original question and there are multiple better ways which are answered here already. My answer is for documentation purpose in case someone is trying to implement tail recursion for string reversal.
def tail_rev(in_string,rev_string):
if in_string=='':
return rev_string
else:
rev_string+=in_string[-1]
return tail_rev(in_string[:-1],rev_string)
in_string=input("Enter String: ")
rev_string=tail_rev(in_string,'')
print(f"Reverse of {in_string} is {rev_string}")
s = input("Enter your string: ")
def rev(s):
if len(s) == 1:
print(s[0])
exit()
else:
#print the last char in string
#end="" prints all chars in string on same line
print(s[-1], end="")
"""Next line replaces whole string with same
string, but with 1 char less"""
return rev(s.replace(s, s[:-1]))
rev(s)
if you do not want to return response than you can use this solution. This question is part of LeetCode.
class Solution:
i = 0
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if self.i >= (len(s)//2):
return
s[self.i], s[len(s)-self.i-1] = s[len(s)-self.i-1], s[self.i]
self.i += 1
self.reverseString(s)