算法分析与设计课程作业第十一周#1#2#3

算法分析与设计课程作业第十一周#1#2#3

对期中练习的01矩阵那道题比较感兴趣,就在leetcode上找了几道思路类似的题目来试试手。题目如下:

62. Unique Paths

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).
How many possible unique paths are there?

Note: m and n will be at most 100.

思路

机器人只能向左或右走,也即是要到某一格,要么从该格的上面那格往下走,要么从该格的左边那格往右走,那么到该格的路径个数即等于到该格上面那格(如果存在)的路径个数加上到该格左边那格(如果存在)的路径个数。
状态转移式:dp[i][j]表示到格ij的路径个数。
所求即dp[m-1][n-1]。
dp[0][0]=0
dp[i][j] = dp[i]0时”>j-1
dp[i][j] = dp[i-1]0且j=0时”>j
dp[i][j] = dp[i-1][j] + dp[i]0且j>0时”>j-1

代码

class Solution {
public:
    int uniquePaths(int m, int n) {
        int dp[m][n];
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                dp[i][j] = 0;
            }
        }
        dp[0][0] = 1;
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(i-1>=0) dp[i][j] += dp[i-1][j];
                if(j-1>=0) dp[i][j] += dp[i][j-1];
            }
        }
        return dp[m-1][n-1];
    }
};

63. Unique Paths II

Follow up for “Unique Paths”:
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as 1 and 0 respectively in the grid.
For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
[
[0,0,0],
[0,1,0],
[0,0,0]
]
The total number of unique paths is 2.
Note: m and n will be at most 100.

思路

与上面基本一样,只是如果某格有障碍,就将该格dp[i][j]设为0,即表示该格既无法到达,也无法从该格出发到其它格(别的格加上该格的dp不会增加)。

代码

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        int m = obstacleGrid.size();
        int n = obstacleGrid[0].size();
        int dp[m][n];
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                dp[i][j] = 0;
            }
        }
        dp[0][0] = 1;
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(i-1>=0) dp[i][j] += dp[i-1][j];
                if(j-1>=0) dp[i][j] += dp[i][j-1];
                if(obstacleGrid[i][j] == 1){
                    dp[i][j] = 0;
                }
            }
        }
        return dp[m-1][n-1];
    }
};

542. 01 Matrix

Given a matrix consists of 0 and 1, find the distance of the nearest 0 for each cell.
The distance between two adjacent cells is 1.
Example 1:
Input:
0 0 0
0 1 0
0 0 0
Output:
0 0 0
0 1 0
0 0 0

Example 2:
Input:
0 0 0
0 1 0
1 1 1
Output:
0 0 0
0 1 0
1 2 1

Note:
The number of elements of the given matrix will not exceed 10,000.
There are at least one 0 in the given matrix.
The cells are adjacent in only four directions: up, down, left and right.

思路

这道题正是期中练习的那道题的英文版。思路跟上两题挺像的,对于一个格离其最近的0的距离,要么其是0,则距离为0,要么就是其相邻四个格中离0最近的格离0距离加1。不过有个问题就是,如果从前往后算,那么正在计算的格的右方格和下方格都是未计算的。所以可以加多一轮从后往前的循环,在第一轮从前往后的循环中,计算从上方左方来的最近0的距离,在第二轮循环中,在通过与从下方右方最近0的距离作比较,得出各格离最近0的距离。
这个思路有个关键需要理解的地方,就是第一次从上到下,前到后的循环中,若某个格计算到的离最近0距离并不是最终其离最近0距离(因为还有右方下方的格要计算),其后面的格用该距离值作计算会不会有问题或不准确?答案是不会的。因为若某个的离最近0距离会在第二次从后往前的循环中变小,该变小是由其后面的格引起的(后面的格有更近的0),所以若后面的格之前有用该格计算,计算结果也更新了,不会有影响;而若该离最近0距离在第二次从后往前的循环中没变,就表明该值,正是其从四个方向来的离0最近的值,没有使用错误。而在第二次从后往前的循环中,算某个离最近0距离所用到的其右方与下方的离最近0距离已经确保正确了,不会出现问题。
还有一个要注意的地方,如果想用递归计算寻找最近0(相当于宽度优先搜索),要注意避免在两个未计算点之间形成死循环(两个点都需要对方先计算才能算出来,从而构成死锁)。

代码

class Solution {
public:

    vector<vector<int>> updateMatrix(vector<vector<int>>& A) {
        int n=A.size(), m=A[0].size();
        vector<vector<int>> ans;
        for(int i = 0; i < n; i++){
            vector<int> row;
            for(int j = 0; j < m; j++){
                row.push_back(1000000);
            }
            ans.push_back(row);
        }

        for(int i =0; i <n; i++){
            for(int j = 0; j < m; j++){
                if(A[i][j]==0)
                    ans[i][j]=0;
                else {
                    if(i&&ans[i-1][j]!=1000000&&ans[i][j]>ans[i-1][j]+1)
                        ans[i][j]=ans[i-1][j]+1;
                    if(j&&ans[i][j-1]!=1000000&&ans[i][j]>ans[i][j-1]+1)
                        ans[i][j]=ans[i][j-1]+1;
                }
            }
        }
        for(int i =n-1; i >=0; i--){
            for(int j = m-1; j >= 0; j--){
                if(A[i][j]==0)
                    ans[i][j]=0;
                else {
                    if(i<n-1&&ans[i+1][j]!=1000000&&ans[i][j]>ans[i+1][j]+1)
                        ans[i][j]=ans[i+1][j]+1;
                    if(j<m-1&&ans[i][j+1]!=1000000&&ans[i][j]>ans[i][j+1]+1)
                        ans[i][j]=ans[i][j+1]+1;
                }
            }
        }
        return ans;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章