最近一位川大的数学博士在网上发文称:华为招数学博士的要求非常奇怪,自己投递了华为数学博士的招聘简历,结果石沉大海,了无音讯,相当于被拒绝了。他就觉得很奇怪:自己是川大数学本硕博,还获得过国家一等奖,怎么就被拒了呢?
而网友的评论告诉了他真相:华为是一家民营企业,不是国家科研机构,是以应用学为主的,是应用型公司,不是理论型公司。还有的说华为要的是数学功底好的程序员等计算机人,而非数学专业的数学人。
--------------下面是今天的算法题--------------
下面我们来看一道华为的面试题,这题是LeetCode的第63题:不同路径 II,难度是中等,这题华为和字节都考过,我们来看下。
问题描述
来源:LeetCode第63题
难度:中等
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?网格中的障碍物和空位置分别用 1 和 0 来表示。
示例1:
输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右
示例2:
输入:obstacleGrid = [[0,1],[0,0]]
输出:1
m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j] 为 0 或 1
动态规划解决
这题让计算从左上角到右下角有多少个不同的路径,这是一道经典的动态规划问题。我们定义dp[i][j]表示从左上角走到位置[i,j]不同路径的个数,因为只能往下走或往右走,所以要走到位置[i,j]可以从上面下来,也就是dp[i-1][j],或者从左边过来,也就是dp[i][j-1],所以总的路径个数就是dp[i-1][j]+dp[i][j-1]。
因为第一行上边是没有数据的,第一列左边也是没有数据的,所以为了减少一些边界条件的判断,可以让dp的宽和高增加 1 ,来看下代码,这里还可以使用滚动数组把二维数组变成一维数组,有兴趣的大家可以自己去优化。
JAVA:
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
int dp[][] = new int[m + 1][n + 1];
// 如果起始点有障碍物,则到不了任何位置。
if (obstacleGrid[0][0] == 1)
return 0;
dp[1][1] = 1;// 如果起始点没有障碍物,到当前位置的路径个数是 1 。
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
if (obstacleGrid[i - 1][j - 1] == 0)
dp[i][j] += dp[i - 1][j] + dp[i][j - 1];// 累加
return dp[m][n];
}
C++:
public:
int uniquePathsWithObstacles(vector<vector<int>> &obstacleGrid) {
int m = obstacleGrid.size();
int n = obstacleGrid[0].size();
vector<vector<int>> dp(m + 1, vector(n + 1, 0));
// 如果起始点有障碍物,则到不了任何位置。
if (obstacleGrid[0][0] == 1)
return 0;
dp[1][1] = 1;// 如果起始点没有障碍物,到当前位置的路径个数是 1 。
for (int i = 1; i <= m; i++)
for (int j = 1; j <= n; j++)
if (obstacleGrid[i - 1][j - 1] == 0)
dp[i][j] += dp[i - 1][j] + dp[i][j - 1];// 累加
return dp[m][n];
}
C:
int uniquePathsWithObstacles(int **obstacleGrid, int obstacleGridSize, int *obstacleGridColSize) {
int dp[obstacleGridSize + 1][(*obstacleGridColSize) + 1];
memset(dp, 0, sizeof dp);
// 如果起始点有障碍物,则到不了任何位置。
if (obstacleGrid[0][0] == 1)
return 0;
dp[1][1] = 1;// 如果起始点没有障碍物,到当前位置的路径个数是 1 。
for (int i = 1; i <= obstacleGridSize; i++)
for (int j = 1; j <= *obstacleGridColSize; j++)
if (obstacleGrid[i - 1][j - 1] == 0)
dp[i][j] += dp[i - 1][j] + dp[i][j - 1];// 累加
return dp[obstacleGridSize][*obstacleGridColSize];
}
Python:
def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
m, n = len(obstacleGrid), len(obstacleGrid[0])
dp = [[0] * (n + 1) for _ in range(m + 1)]
# 如果起始点有障碍物,则到不了任何位置。
if obstacleGrid[0][0] == 1:
return 0
dp[1][1] = 1 # 如果起始点没有障碍物,到当前位置的路径个数是 1 。
for i in range(1, m + 1):
for j in range(1, n + 1):
if obstacleGrid[i - 1][j - 1] == 0:
dp[i][j] += dp[i - 1][j] + dp[i][j - 1] # 累加
return dp[m][n]
最后给大家推荐一个副业专栏,副业大咖老秦出品,光副业变现就超7位数,感兴趣的朋友可以入手看一下: