算法分析與設計課程作業第十一週#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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章