Facebook高频题 | Shortest Word Distance的多个变种和解法

Shortest Word Distance是Facebook、LinkedIn等公司的高频面试题。

这个题目本身不是很难,但却有很多follow up问题。今天我们就针对这个题目进行讲解和延伸,帮助大家梳理拓宽思路,更好接招面试官的层层追问。

先一起来看看题目:

题目描述

Given a list of words and two words word1 and word2, return the shortest distance between these two words in the list.

Note:

You may assume that word1 does not equal to word2, and word1 and word2 are both in the list.

Example:

Assume that words = ["practice", "makes", "perfect", "coding", "makes"].

Input:word1 = “coding”, word2 = “practice”Output:3

Input:word1 = "makes", word2 = "coding"Output:1

考点解析

shortest word distance是Facebook非常高频的一道面试题目。

这道题目有很多变种。不同于以往我们把一个题目讲的比较细致,今天这个题目,我们希望将多个变种串起来讲,并且再多延伸一些。

希望通过这道习题,帮助大家开阔思路,了解这个看似不那么困难的题目,在面试中会怎样被面试官步步延伸和追问。这也正是facebook特别喜欢考这道题的原因。

主讲人:Emma老师

FLGU一线公司资深工程师

​扫描下方二维码

进入来Offer官网观看

解题思路

在这道题目中,Emma老师讲解了多个不同的解法,以及follow up问题的回答思路。

Solution 1: Naive Solution

拿到题目,一个比较自然的想法就是把array从左到右遍历一遍,记录word1和word2所出现的位置,得到两个sorted index list。

以下面的这个例子来说:

 0  1  2  3  4  5  6  7

[a, c, d,b, b, b, c,a]

Input:

word1 = "a"

word2 = "b"

则遍历后的list分别为:

la: 0, 7       

lb: 3, 4, 5   

经过这一步的处理,这个题目就变成了从la取一个数字,从lb取一个数字,差值最小的组合是什么。

最brute force的做法,就是计算出所有可能的组合的差,再从中选择最小的一对。但显然,这是一个复杂度比较高的做法,我们可以在这个基础上进行优化。

Optimize 1: Binary Search

已知这两个list都是排好序的,那我们就可以利用binary search:

对于a里面的每一个元素,在b里面进行binary search,找到离a中元素最近的那个元素。之后再在所有结果中取一个最近的结果。

思考题

对a中的元素在b中进行binary search,和对b中的元素在a中进行binary search时间复杂度有区别吗?

Optimize 2: Two Pointer

再进一步,两个list都是sorted,要找到最小距离的情况,我们应该可以想到,这是一个典型的two pointer谁小移谁的问题。

我们可以分别在a、b两个list放置两个pointer,每次移动两个pointer中,对应的元素中相对较小的一个,同时计算一下两个pointer对应元素相差的距离,在需要更新的时候更新。

也就是说:

if la(i) is smaller, lb(j) is the smallest larger element in lb comparing to la(i)

if lb(j) is smaller, la(i) is the smallest larger element in la comparing to lb(j)

Solution 2

我们是否可以不建这两个list呢?能否只是从左到右遍历一遍原array,忽略无关的元素,只去看a和b呢?也是可以的。

我们换一种分解问题的方法,把这个问题考虑为:

For each a, we need to get the most recent position of b.

For each b, we need to get the most recent position of a.

这样他们中差值最小的那个,就是我们需要的答案。

那么在实现的时候,我们就需要从左到右扫一遍array,并记录:

IndexA:最近一次出现a的位置

IndexB:最近一次出现b的位置

Result:当前的最短距离

每当我们找到一个a或者b时,我们就要检查IndexB和IndexA之间的差是否比result的值小,如果是,则更新result的值,直到遍历完整个array。

在讲解Follow Up问题前,我们先看一下这个解法的代码实现:

代码实现

Follow Up 1: 

Multiple query with unlimited times

原问题只是query一次,而且是确定的两个单词。那么,如果是要query很多次,而且单词是不固定的,那么应该怎样更好的解决这个问题呢?

在这种情况下,如果使用之前的方法,我们就需要在每次query的时候都把array扫一遍,cost非常大。


我们应该想到这个题目的需要precomputation


比较直接的一个方法,就是使用一个hashmap,记录所有distinct word出现的位置。那么,在query某两个word的时候,只需要看那两个word的list就可以了。省去了反复遍历原array的时间。

进一步,还可以和面试官探讨,如果某个组合被query了很多次,那我们是否需要cache这个结果。

另外一个要与面试官讨论的就是,假设我需要非常快的返回这个结果,而且重复query的情况非常多。那我可能需要直接将每两个word的最短距离直接记下来,这样之后的每次query都只需要O(1)的时间了。

思考题:

如果这样的话,precomputation的效率如何,有没有什么tradeoff?是否是所有情况下都合适的方法?

Follow Up 2: 

Find the Shortest Word Distance 

Among k Words

这个题目的另一种变形方式就是,我不只求2个word的最短距离,而是多个word的最短距离。

这里距离的定义是在原input array中最小的subarray的长度,这个subarray需要包含所有k个指定的words。

那这时又要如何求解呢?

与上面思路相承接,一个可能的解法是,针对k个字母,都建立一个list。问题转化为:从这k个list中,各抽一个元素,使得其最大值和最小值的差最小。

这时,我们利用k pointer的方法,使用priority queue,tree set或者tree map等数据结构都可以解决。

另一个思路,是将这道题目与minimum substring window联系起来,可以用sliding window的方法来解决。



更多科技求职资讯,请关注”来Offer”


阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭