google面经(挂了) - 未名空间(mitbbs.com)
1. 二维matrix,含0,1。 1是障碍。
00011
11100
从左上角出发到右下角, 可以往上,往下,往右移动。
把1变成0,使得你可以从左上角到右下角。
求最小的变化数字。
一般的题目是限定只能向下走和向右走,这样的话DP大家都是知道的,就是按逆对角刷
DP:
a(i,j) = min(cost(i,j+1) + a(i,j+1), cost(i+1,j) + a(i+1,j))
这个题目说可以向上走,使得为题复杂化了。但是只需改进DP方式仍然可以解决。这次
我们从右向左逐列刷DP。对于第j列,
for i = 1 to n, a_r(i,j) = cost(i,j+1) + a(i,j+1)
for i = 1 to n, a_u(i,j) = min(a_r(i,j), cost(i-1,j) + a_u(i-1,j))
for i = n to 1, a_d(i,j) = min(a_r(i,j), cost(i+1,j) + a_d(i+1,j))
for i = 1 to n, a(i,j) = min(a_r(i,j), a_u(i,j), a_d(i,j))
a_r(i,j)记录的是从i,j向右走的最佳方式。
a_u(i,j)记录的是从i,j向上走的最佳方式。
a_d(i,j)记录的是从i,j向下走的最佳方式。注意计算a_d的时候要从下往上,e.g. for
n to 1.
这样每个点只算了三次,整体复杂性依然是线性的。
这个加强版的DP可以解决普遍的问题,不局限于矩阵的值只能是0或1。
第一题我会用flood fill + m×n 空间
http://shibaili.blogspot.com/2015/07/google-interview-questions-3.html
2个角度(dfs / bfs)
#1 找出所有路径中,含1最少的那个路径
#2 最短路径,每个路径weight为0或者1, dijkstra
Dijkstra为O(n*lgn),可用2个queue降低复杂度为O(n)。因为edge的weight只为0或1
2。 两个区间,左闭右开。数字可以是整数或者浮点,
要你判断两个区间是否相交。
特殊例子需要你自己定义。
Read full article from google面经(挂了) - 未名空间(mitbbs.com)
1. 二维matrix,含0,1。 1是障碍。
00011
11100
从左上角出发到右下角, 可以往上,往下,往右移动。
把1变成0,使得你可以从左上角到右下角。
求最小的变化数字。
一般的题目是限定只能向下走和向右走,这样的话DP大家都是知道的,就是按逆对角刷
DP:
a(i,j) = min(cost(i,j+1) + a(i,j+1), cost(i+1,j) + a(i+1,j))
这个题目说可以向上走,使得为题复杂化了。但是只需改进DP方式仍然可以解决。这次
我们从右向左逐列刷DP。对于第j列,
for i = 1 to n, a_r(i,j) = cost(i,j+1) + a(i,j+1)
for i = 1 to n, a_u(i,j) = min(a_r(i,j), cost(i-1,j) + a_u(i-1,j))
for i = n to 1, a_d(i,j) = min(a_r(i,j), cost(i+1,j) + a_d(i+1,j))
for i = 1 to n, a(i,j) = min(a_r(i,j), a_u(i,j), a_d(i,j))
a_r(i,j)记录的是从i,j向右走的最佳方式。
a_u(i,j)记录的是从i,j向上走的最佳方式。
a_d(i,j)记录的是从i,j向下走的最佳方式。注意计算a_d的时候要从下往上,e.g. for
n to 1.
这样每个点只算了三次,整体复杂性依然是线性的。
这个加强版的DP可以解决普遍的问题,不局限于矩阵的值只能是0或1。
第一题我会用flood fill + m×n 空间
http://shibaili.blogspot.com/2015/07/google-interview-questions-3.html
2个角度(dfs / bfs)
#1 找出所有路径中,含1最少的那个路径
#2 最短路径,每个路径weight为0或者1, dijkstra
Dijkstra为O(n*lgn),可用2个queue降低复杂度为O(n)。因为edge的weight只为0或1
bool bfs(vector<vector<int> > &grid,vector<vector<bool> > &visit,queue<pair<int,int>> &q1,queue<pair<int,int>> &q2) { while (!q1.empty()) { int row = q1.front().first; int col = q1.front().second; if (row == grid.size() - 1 && col == grid[0].size() - 1) { return true; } q1.pop(); if (row + 1 < grid.size() && !visit[row + 1][col]) { visit[row + 1][col] = true; if (grid[row + 1][col] == 0) { q1.push(make_pair(row + 1,col)); }else { q2.push(make_pair(row + 1,col)); } } if (row - 1 >= 0 && !visit[row - 1][col]) { visit[row - 1][col] = true; if (grid[row - 1][col] == 0) { q1.push(make_pair(row - 1,col)); }else { q2.push(make_pair(row - 1,col)); } } if (col + 1 < grid[0].size() && !visit[row][col + 1]) { visit[row][col + 1] = true; if (grid[row][col + 1] == 0) { q1.push(make_pair(row,col + 1)); }else { q2.push(make_pair(row,col + 1)); } } if (col - 1 >= 0 && !visit[row][col - 1]) { visit[row][col - 1] = true; if (grid[row][col - 1] == 0) { q1.push(make_pair(row,col - 1)); }else { q2.push(make_pair(row,col - 1)); } } } return false;}int findPath(vector<vector<int> > &grid) { int m = grid.size(); int n = grid[0].size(); queue<pair<int,int>> q1; queue<pair<int,int>> q2; int count = 0; q1.push(make_pair(0,0)); vector<vector<bool> > visit(m,vector<bool>(n,false)); visit[0][0] = true; while (!q1.empty()) { if (bfs(grid,visit,q1,q2)) { return count; } count++; queue<pair<int,int>> empty; q1 = q2; swap(q2,empty); } return -1;}2。 两个区间,左闭右开。数字可以是整数或者浮点,
要你判断两个区间是否相交。
特殊例子需要你自己定义。
Read full article from google面经(挂了) - 未名空间(mitbbs.com)