I got this question in a Java interview today.
I have to implement a collection which is an array and have add
and delete
methods which can perform only at the end of an array.
In addition to that I have to implement two more methods which is the undo
and redo
methods which can be performed only once.
For example:
Let x be an array containing {1,5,7,9}.
Now I add {44,66,77}
in it and make it {1,5,7,9,44,66,77}
.
Now when I undo it, the array should delete {44,66,77}
. And if I do redo afterwards, it should be back to {1,5,7,9,44,66,77}
.
And similarly for the delete.
What is the best way to achieve this in terms of complexity and memory?
My solution to the interviewer:
Which is a totally incorrect solution as per interviewer.
If “UNDO” string is encountered, pop the top element from Undo stack and push it to Redo stack. If “REDO” string is encountered, pop the top element of Redo stack and push it into the Undo stack. If “READ” string is encountered, print all the elements of the Undo stack in reverse order.
Have a method called flatten() that uses the data in the bitmap history to get the contents of the array and create a single array from it. Now when you want to undo, all you do is decrement the End Index value. And to redo, just increment the End Index value.
Most Python commands which affect the underlying state of an object create an undo/redo action which can then be undone or redone through Python or through the Edit > Undo and Redo menu items.
I would solve it like this. Basically, there will be three lists.
Command
interfaceRedo list with instances of Command
interface (optional, explained below)
public interface Command {
void do();
void undo();
}
There will be two Command
implementations: AddCommand
and RemoveCommand
.
add()
, new instance of AddCommand
created and added to the undo list. Then we call do()
of this command, which modifies actual values and stores index
of added item.remove()
, new instance of RemoveCommand
created and added to the undo list. Then we call do()
of this command, which modifies actual values and stores index
and value of removed item.undo()
we pull last command from the undo list and execute undo()
method of this command. The command pushed to the redo list. Undo methods of AddCommand
and RemoveCommand
revert changes back.redo()
we pull last command from the redo list and execute do()
method again. Pulled command gets added to undo list.Another optimization would be to remove redo list and use undo index instead. In this case when you undo()
, you don't need to remove/add value from the list, but just decrease the undo index by one. Similarly, redo()
will increase it by one.
Thus the final solution will have list of values, undo list and an index value.
Update:
For the simplest case, where only one undo()
/redo()
operation is required, solution will look even simpler. Instead of having undo list and index, it's enough to store the latest command instance. Thus you we will have a list of values and an instance of last undo command.
Either I misunderstand the question, or people are overthinking this. The question has quite a lot of constraints, so:
Then just update these on each different operation. No stacks or anything are needed, because multiple undo/redo is not needed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With