实现数组的撤消和重做

2022-09-02 20:41:51

我在今天的Java面试中得到了这个问题。

我必须实现一个集合,它是一个数组,并且有和方法只能在数组的末尾执行。adddelete

除此之外,我还必须实现另外两种方法,即只能执行一次的和方法。undoredo

例如:

设 x 为包含{1,5,7,9}.

现在我添加它并制作它。{44,66,77}{1,5,7,9,44,66,77}

现在,当我撤消它时,数组应该删除。如果我事后重做,它应该回到.{44,66,77}{1,5,7,9,44,66,77}

同样,对于删除。

在复杂性和内存方面实现这一目标的最佳方法是什么?

我对面试官的解决方案:

  1. 创建一个存储最后一个操作的字符串字段,即“添加”/“删除”。
  2. 以及一个哈希图,它将键存储为数组的索引,将值存储为数组的索引值。

根据面试官的说法,这是一个完全不正确的解决方案。


答案 1

我会这样解决它。基本上,将有三个列表。

  • 包含实际值的列表
  • 包含接口实例的撤消列表Command
  • 包含接口实例的重做列表(可选,如下所述)Command

    public interface Command {
        void do();
        void undo();
    }
    

将有两个实现:和 。CommandAddCommandRemoveCommand

  • 在 上,已创建并添加到撤消列表中的新实例。然后,我们调用此命令,该命令修改实际值和添加项的存储。add()AddCommanddo()index
  • 在 上,已创建并添加到撤消列表中的新实例。然后我们调用此命令,该命令修改实际值以及已删除项的存储和值。remove()RemoveCommanddo()index
  • 在我们从撤消列表中拉取最后一个命令并执行此命令的执行方法。命令推送到重做列表。撤消 方法并将更改还原回来。undo()undo()AddCommandRemoveCommand
  • 在上,我们从重做列表中拉出最后一个命令,然后再次执行方法。拉取命令将添加到撤消列表中redo()do()

另一个优化是删除重做列表并改用撤消索引。在这种情况下,您不需要从列表中删除/添加值,只需将撤消索引减少一个即可。同样,将增加一个。undo()redo()

因此,最终解决方案将具有值列表撤消列表索引值

更新:

对于最简单的情况,只需要一个/操作,解决方案看起来会更简单。无需撤消列表索引,只需存储最新的命令实例即可。因此,您将拥有一个值列表上次撤消命令的实例。undo()redo()


答案 2

要么是我误解了这个问题,要么是人们过度思考这个问题。这个问题有很多限制,所以:

  • 当前内容的数组
  • 上次删除的项目的额外数组(需要撤消删除/重做添加)
  • 一个变量用于数组的先前长度(需要撤消添加/重做删除)
  • 一个枚举变量用于最后一个操作(添加/删除)
  • 一个布尔值,用于说明撤消是否刚刚完成

然后只需在每个不同的操作上更新这些。不需要堆栈或任何内容,因为不需要多次撤消/重做。