【发布时间】:2019-02-13 22:30:06
【问题描述】:
因为我喜欢用 Scala 编程,所以在我的 Google 面试中,我请他们给我一个 Scala / 函数式编程风格的问题。我得到的Scala函数式问题如下:
您有两个由字母字符和一个表示退格符号的特殊字符组成的字符串。我们称这个退格字符为“/”。当您使用键盘时,您键入此字符序列,包括退格/删除字符。您要实施的解决方案必须检查两个字符序列是否产生相同的输出。例如,“abc”、“aa/bc”。 “abb/c”、“abcc/”、“/abc”和“//abc”都产生相同的输出“abc”。因为这是一个 Scala / 函数式编程问题,所以您必须以惯用的 Scala 风格实现您的解决方案。
我写了以下代码(它可能与我写的不完全一样,我只是记忆犹新)。基本上我只是线性遍历字符串,将字符添加到列表中,然后比较列表。
def processString(string: String): List[Char] = {
string.foldLeft(List[Char]()){ case(accumulator: List[Char], char: Char) =>
accumulator match {
case head :: tail => if(char != '/') { char :: head :: tail } else { tail }
case emptyList => if(char != '/') { char :: emptyList } else { emptyList }
}
}
}
def solution(string1: String, string2: String): Boolean = {
processString(string1) == processString(string2)
}
到目前为止这么好?然后他询问时间复杂度,我回答线性时间(因为您必须处理每个字符一次)和线性空间(因为您必须将每个元素复制到列表中)。然后他让我在线性时间内完成,但空间恒定。我想不出一种纯粹实用的方法。他说尝试使用 Scala 集合库中的函数,例如“zip”或“map”(我清楚地记得他说过“zip”这个词)。
事情就是这样。我认为在没有任何可变状态或副作用的情况下,在恒定空间中执行它是物理上不可能的。就像我认为他搞砸了这个问题。你怎么看?
你能在线性时间内解决它,但空间不变吗?
【问题讨论】:
-
由于
immutability是函数式编程的基石之一,您必须创建字符串/列表/数组的副本,这意味着在恒定空间中执行任何操作似乎都不可行。就zip而言,它的任何用法都意味着定义为线性空间。 -
无论你做什么,你都需要以某种方式构造输出。输出大小为 O(n)。我可以看到如何恢复 O(1) 空间的唯一方法是,如果您可以在构造部分输出的同时删除部分输入。但是
Strings 没有有 部分可以丢弃,所以这似乎是不可能的。例如,如果输入是字符的反向列表,这将是微不足道的。其他想法,比如重用输入字符串的部分,也有同样的问题:字符串没有部分,所以你必须保留一个切片索引列表,但该列表占用 O(n) 空间。 -
元评论:你真的可以要求面试官就特定主题提出问题吗?我觉得这很令人惊讶。
-
@SarveshKumarSingh 如果你使用 Scala 视图,你可以在
O(1)additional 空间中压缩两个集合 -
@JörgWMittag
solution必须比较这两个字符串描述,它不必对它们进行规范化。输出为Boolean,占用固定空间。
标签: scala functional-programming scala-collections purely-functional