专栏名称: 九章算法
专业的北美IT求职经验分享、技术交流社区,帮助你找到好的IT工作。由硅谷顶尖IT企业工程师维护。提供专业的算法培训/面试咨询,官网 www.jiuzhang.com
目录
相关文章推荐
算法爱好者  ·  再见!Skype!—— 代码不朽,但时代无情 ·  昨天  
九章算法  ·  寻找一个leetcode刷题搭子 ·  昨天  
算法爱好者  ·  突发!4 个程序员被抓,维护赌博网站每月赚 ... ·  2 天前  
算法与数学之美  ·  人工智能时代,内容的减法是时代的需要 ·  3 天前  
算法爱好者  ·  55 ... ·  3 天前  
51好读  ›  专栏  ›  九章算法

Google 面试题 | 建邮局

九章算法  · 公众号  · 算法  · 2017-02-23 03:34

正文


1
题目描述


给你一个二维网格,每个格子是房子 1 或者空地 0。找到一个空地修建一个办公室,使得这个办公室到所有的房子的距离之和最小。 返回最小的距离和。如果无法修建,那么返回 -1.

样例:


返回6。


2
算法分析


1. 因为这个题目要求无解的时候返回 -1 ,那么我们就先想一下无解的情况。


(1)网格不存在,即行数为0或者列数为0;
(2)网格存在,但是没有地方修,也就是没有空地。

之后就要开始要想如何解决这个问题了。


2. 题目是要求所有的房子到某一空地的最小曼哈顿距离和,那我们就有一个朴素的想法 ,直接枚举所有的空地,求出所有的房子到该空地的曼哈顿距离和,从这些距离和中选取最小的一个即可。


(ps:曼哈顿距离:dis=|x2-x1|+|y2-y1|)


伪代码:

接下来就是改进这个朴素的做法。

3. 观察上述伪代码,显然求所有的房子到某一点的曼哈顿距离和是可以通过预处理实现O(1)询问的。


这里就要先提到 有关曼哈顿距离的一个常用技巧了:将曼哈顿距离拆分成 X 轴距离与 Y 轴距离。


设两个点:(x1,y1)、(x2,y2)
曼哈顿距离:dis=|x2-x1|+|y2-y1|

根据上面这个式子,我们就可以把求两个点的曼哈顿距离拆分成求两个点在 X 轴上的距离与求两个点在 Y 轴上的距离。

有了这个拆分,就有了预处理的基础。

4. 我们现在以对 X 轴距离做预处理为例进行讲解。


我们先预处理出一个rowSum数组,rowSum[i]记录第 i 行一共有几个房子。


那么对于一个点(i,j),从第 0 。。。i 行的所有房子到该点的 X 轴距离和即等同于从第0。。。i 行的所有房子到第 i 行的 X 轴距离和。


用prefixSum1[i]表示从第0。。。i 行的所有房子到第 i 行的一共有多少房子;
用prefixSum2[i]表示从第0。。。i 行的所有房子到第 i 行的X 轴距离和,即得到下式:



根据推导的式子,prefixsum1与prefixsum2都可以通过O(row)的预处理得到。


这样我们就得到了从第0。。。i 行的所有房子到第 i 行的 X 轴距离和。


同理,还可以通过 O(row) 的预处理得到从第 i 。。。n - 1 行的所有房子到第 i 行的 X 轴距离和。

将以上的两个预处理的值相加,即可得到:所有的房子到第 i 行的距离和,将其记为ansRow[i]。

综上,我们就可以通过O(row)的预处理得到所有房子到某一 行的距离和,并记录在ansRow[] 数组里。

5. 通过与第四点相同的思路,我们可以通过一个O(column)的预处理得到所有房子到某一列的距离和,并记录在ansColumn[] 数组里。


于是,所有房子到某一点(i,j)的曼哈顿距离和即为:ansRow[i] + ansColumn[j]。
代码的总体复杂度就下降到了O(row*column)。


3
参考代码



4






请到「今天看啥」查看全文