Is there any algorithm/technique in which string reversal by words can be done in single pass with time complexity of O(n) and space complexity of O(1).
-
2could you add a simple in / out example? – RichardPlunkett Dec 18 '13 at 01:57
-
@RichardPlunkett It's string reversal. Pick some words. – Hunter McMillen Dec 18 '13 at 01:58
-
1input : Hello world output: world hello – Abhishek Dec 18 '13 at 01:59
-
@FlightOdyssey I meant in place reversal i.e reversal by not using any buffer to store result apart from original input – Abhishek Dec 18 '13 at 02:01
-
Space complexity O(1) implies in-situ – RichardPlunkett Dec 18 '13 at 02:01
-
1O(1) space and O(N) time are straight forward enough. Single pass might be a bit tricky. – RichardPlunkett Dec 18 '13 at 02:02
-
you care to waive the whole single pass constraint? – RichardPlunkett Dec 18 '13 at 02:04
-
1related: [Given an array of characters which form a sentence of words, give an efficient algorithm to reverse the order of the words (not characters) in it](http://stackoverflow.com/q/47402/4279) – jfs Dec 18 '13 at 02:04
-
yep, the code is very C-ish, but reverse each of the words internally, and separately reverse whole string, simple, fast, but two passes, arguably 3, since the word boundary scan and the word revese are each a separate pass action. – RichardPlunkett Dec 18 '13 at 02:06
-
@J.F.Sebastian it reverses in two pass,I need in single pass – Abhishek Dec 18 '13 at 02:14
-
@Abhishek: I know. "related" doesn't mean "the exact same". It would be "duplicate" otherwise. – jfs Dec 18 '13 at 02:18
-
@J.F.Sebastian your right,no hard feelings.But it didnt solve my cause – Abhishek Dec 18 '13 at 02:21
-
Can I use a quantum computer? – bishop Dec 18 '13 at 02:48
-
Voting to close as a duplicate of [the question J.F.Sebastian linked](http://stackoverflow.com/q/47402/4279), as a single pass is not possible. – Bernhard Barker Dec 18 '13 at 05:54
-
@Dukeling: even if single pass were not possible; then the answer to this question would contain the proof. – jfs Dec 18 '13 at 06:49
-
@J.F.Sebastian I already want to mark questions asking about different time and space complexities as duplicates - all the approaches really should be contained in one post, but I understand that some people may not want that ('that', but not so much 'why' - unless it's just because [so] doesn't cater for this too well). So if a question comes along asking about **the same** complexities with an impossible constraint added, I'd definitely vote that it be a duplicate. – Bernhard Barker Dec 18 '13 at 08:20
3 Answers
No, this is not possible in one pass unless you already know how long each word is or are allowed to use some sort of buffer.
Try it:
HELLO SAM
^
becomes
SAM HELLO
^
If all you know is the E
(since this is your first/only pass, and you aren't allowed to store any data), you can't possibly know that it needs to be swapped to where the space character currently is. Once you reach the space and find out where the E
belongs, it's too late to retrieve the E
again.

- 2,267
- 18
- 25
-
@Dukeling: I am talking about the latter (otherwise you would in fact know the position to be simply `n-i-1`), and I have changed the example to remove any ambiguity. Thanks! – Flight Odyssey Dec 18 '13 at 23:32
-
if word length is limited (independent from `n`) then you can read to the end of the word. And [O(n)-time one-pass, O(1)-space algorithm is possible](http://stackoverflow.com/a/20649255/4279). – jfs Dec 19 '13 at 04:43
If we can get characters in reverse order and each word requires no more than O(1)
machine words in memory then to reverse words in a single pass, O(n)-time, O(1)-space algorithm could be used (pseudo-code):
def reverse_words(text):
word = [] # assume a word requires O(1) machine words
for character in reversed(text): # single pass (in reverse)
if character == ' ':
if word: # print non-empty word
print(''.join(reversed(word)), end=character)
word = []
else:
word.append(character) # O(1)-time
if word: # print the first word (in original text) if it is not empty
print(''.join(reversed(word)))
Example:
>>> reverse_words("this is a string")
string a is this
Note: each character is touched twice: first -- append, second -- print it. To understand why it is still one-pass algorithm, imagine instead of text
we are given poplast()
function that pops (get and remove) the last character from a character sequence. If it returns None
for an empty sequence then the loop would look like:
for character in iter(poplast, None): # call `poplast()` until it returns `None`
# the rest is the same as in the first loop ..
In this case we can't make more than one pass over the input. It is destroyed on the first pass.
is it possible to change original text itself?
Yes. Again if we can assume that the longest word length is constant (independent from n
) i.e., if n
grows; the max word length stays the same.
Just read one word at a time from both ends into two temporary buffers. And swap them while keeping track of unused ends due to uneven word sizes on different ends. Only one temporary buffer won't be empty after the swap (the one that has an incomplete word). Fill buffers until the full word is encountered on either ends or the center is reached. Then repeat the swap.
I can't think of an elegant implementation. And I don't see the point of one-pass requirement if we have random access to the input. Look at how tac
utility or tail -r
(BSD) are implemented (a line plays a role of a single word in this case) for very large files that do not fit in memory.
-
@Dukeling: It is a single pass. Imagine `reversed(text)` *never ends*. The function still works. The only "big" assumption is that words are finite. – jfs Dec 18 '13 at 06:45
-
Scratch my last comment. The assumption that word lengths have a (constant) upper bound isn't unreasonable, but from a theoretical standpoint (for the sake of interest, or for an interview), I don't think it should be made. And 'word' may not have been intended to mean a meaningful sequence of characters, but rather just a sequence of characters. Also, this prints it out as opposed to putting the characters back into the same string (the latter may be desired and would not be possible in O(1) here). – Bernhard Barker Dec 18 '13 at 07:49
-
@J.F.Sebastian ,If reversal of words is given it can be done in single pass but What I need is given string shld be reversed by words in "single pass " only. – Abhishek Dec 18 '13 at 13:16
-
@Abhishek: If the words can be arbitrary large e.g., the whole n-characters could be a single word then [update your question](http://stackoverflow.com/posts/20648333/edit) and say so explicitely. I'm not sure I understand your comment. Could you elaborate? – jfs Dec 18 '13 at 13:42
-
I meant string reversal by words can be done in two pass by first reversing entire string n then reversing until we get a space .So ur algo uses reversal of entire string to solve.In the end ur using two pass ,But i need it to be done in single not two pass – Abhishek Dec 18 '13 at 16:34
-
@Abhishek: it is a single pass. I elaborate a bit in [this comment](http://stackoverflow.com/questions/20648333/string-reversal-by-word-in-single-pass/20649255?noredirect=1#comment30954440_20654399) – jfs Dec 19 '13 at 02:27
-
@J.F.Sebastian ,sorry didnt ssaw the code properly it is single pass ,but cant we change the original text itself instead of using buffer like uve used – Abhishek Dec 19 '13 at 03:39
-
@J.F.Sebastian Im not saying your are wrong.But I just wanna is it possible to change original text itself? – Abhishek Dec 19 '13 at 03:43
-
-
The more I see of python the more impressed I am with it. Had to look up 'reversed' to discover it wasn't itself O(n). Upvoted for noting that each element "touched twice" but input list walked only once. – Speed8ump Dec 19 '13 at 06:07
If considering a word can have maximum number of character is 20, we can achieve O(1) space, O(n) time and one single pass :)
public static void main(String[] args) {
reverse("Hello World HaHa");
}
public static void reverse(String line) {
char[] stack = new char[20];
int index = 0;
for (int i = line.length() - 1; i >= 0; i--) {
if (line.charAt(i) != ' ') {
stack[index++] = line.charAt(i);
} else {
while (--index >= 0) {
System.out.print(stack[index]);
}
System.out.print(' ');
index = 0;
}
}
if (index > 0) {
while (--index >= 0) {
System.out.print(stack[index]);
}
}
}
Note: the actual time complexity is 2n with n is the length of the string, but single pass!

- 11,204
- 2
- 24
- 43
-
I believe this is the same approach as [J.F.'s answer](http://stackoverflow.com/a/20649255/1711796). Note [my comment there](http://stackoverflow.com/questions/20648333/string-reversal-by-word-in-single-pass?noredirect=1#comment30917729_20649255). – Bernhard Barker Dec 18 '13 at 10:23
-
@Pham Trung ,you are using buffer.So it wont hold space complexity of O(1). – Abhishek Dec 18 '13 at 13:13
-
1@Abhishek: any buffer of a fixed size (`20` in this case) that doesn't depend on `n` satisfies `O(1)` space requirement. You may say that the code fails if a word is larger than 20 characters. But your question says nothing about possible word size. – jfs Dec 18 '13 at 13:49
-
@Abhishek as [J.F.Sebastian](http://stackoverflow.com/users/4279/j-f-sebastian) mentioned, any "constant" space will be considered O(1). – Pham Trung Dec 18 '13 at 14:19
-
Depends on your definition of "single pass". Assuming you define one-pass as one pass over the input array this is one-pass. If you define one-pass as the number of times you iterate through each input item this is two pass. Also, you can implement this method without the temporary array, eliminating the 20 character limit. – Speed8ump Dec 18 '13 at 17:46
-
@Speed8ump: without the temporary array the input would be required to be read twice. `String` in the `reverse()` function can be replaced by an object that returns one character at a time (in reverse) and doesn't allow `seeking` e.g., you are given `pop()` method that pops characters from the end of a container (you can't go back/seek in the container and obviously it is one-pass because `pop()` destroys content). – jfs Dec 19 '13 at 02:26
-
@Speed8ump as I have noted in my answer, the time complexity is 2n , but considering pass means reading from the "input" (which is String line in the code), this is one pass. – Pham Trung Dec 19 '13 at 03:09
-
@PhamTrung u may be right but what if the string length is greater tham 20? – Abhishek Dec 19 '13 at 03:51
-
@Abhishek you mean the "word" length? The string length can be any number. The word length is my assumption. The array char can be change to a dynamic data structure, but the O(1) space cannot be ensured anymore – Pham Trung Dec 19 '13 at 05:14
-
@PhamTrung thn it'll solve but I got my required solution from JF Sebestian's post – Abhishek Dec 19 '13 at 05:20