leetcode - [動態規劃] -最大加號標誌(764)

1、問題描述

在一個大小在(0,0)到(N-1,N-1)的2D網格grid中,除了mines給出的單元格爲0,其他單元格都爲1。網格中包含1的最大軸對稱加號的階是多少,返回最大軸對稱加號的階。如果不存在軸對稱加號,則返回0.
一個k階軸由1組成的軸對稱加號指的是具有中心網格grid[x][y],以及從中心向上、向下、向左、向右延伸,長度爲k-1,由1組成的臂,下面給出 k" 階“軸對稱”加號標誌的示例。

階 1:
000
010
000

階 2:
00000
00100
01110
00100
00000

階 3:
0000000
0001000
0001000
0111110
0001000
0001000
0000000

示例1:

輸入: N = 5, mines = [[4, 2]]
輸出: 2
解釋:

11111
11111
11111
11111
11011

在上面的網格中,最大加號標誌的階只能是2。一個標誌已在圖中標出。

示例2:

輸入: N = 2, mines = []
輸出: 1
解釋:

11
11
沒有 2 階加號標誌,有 1 階加號標誌。

2、解題思路

思路1暴力法。我們可以每個爲“1”的單元格爲中心,計算其向上、向下、向左、向右四個方向的臂長(即該單元格向這個四個方向的連續“1”的個數),這個臂長中的最小值即爲以該單元格爲中心的軸對稱加號的階。
這種方法的時間複雜度爲O(N3)O(N^3),空間複雜度爲O(1)O(1).

思路2動態規劃 - 優化的暴力法。其實,對於值爲每個單1的單元格,其向左、向右、向上、向下四個方向的連續“1”的個數是可以提前計算出來的。
比如,對於某一行[1,0,1,1,1,0,1,1][1,0,1,1,1,0,1,1],每個位置向左方向連續“1”的個數爲[1,0,1,2,3,0,1,2][1,0,1,2,3,0,1,2]
具體的計算方法如下:

/*注意:
下列算法row[j]表示某一行的第j列元素;
dp[j]表示從左邊界開始到row[j]連續1的個數。
*/
#for j = 0 to len:
	*if(row[j] == 0):
		#dp[j] = 0;
	*else if(row[j] == 1):
		#if(j > 0 && row[j-1] == 1):
			*dp[j] = dp[j-1]+1;
		#else:
			*dp[j] = 1;
			

只要使用類似上述的方法求出每個爲“1"的單元格向上、向下、向左、向右四個方向的連續1的個數,並存儲在up、down、left、right中,則以該單元格爲中心的軸對稱加號的階爲min{left,right,up,down};

時間複雜度:O(N2)O(N^2).
空間複雜度:O(N2)O(N^2).

3、代碼實現

/*基本思想:
對於每個網格grid[r][c],分別計算從gird[r][c]開始, left、right、up、down四個方向上1的連續個數,
並把它們存儲下來,則以grid[r][c]爲中心的軸對稱加號標誌的最大階
dp[r][c] = min{left[r][c],right[r][c],up[r][c],down[r][c]} 
計算left[r][c]的規則如下:
(1) 如果grid[r][c] 等於0,則left[r][c]爲0;
(2) 如果grid[r][c]等於1並且它的前一個也爲1,則left[r][c] = left[r][c-1] + 1, 否則left[r][c] = 1;
假設gird有一行爲0111011,則left爲0123012*/
class Solution {
public:
    int orderOfLargestPlusSign(int N, vector<vector<int>>& mines) {
        vector<vector<int>> grid(N,vector<int>(N,1));
        for(int i = 0; i < mines.size(); i++){
            grid[mines[i][0]][mines[i][1]] = 0;
        }
        vector<vector<int>> left(N,vector<int>(N,0));
        vector<vector<int>> right(N, vector<int>(N,0));
        vector<vector<int>> up(N,vector<int>(N,0));
        vector<vector<int>> down(N, vector<int>(N,0));
        for(int i = 0; i < N; i++){
            for(int j = 0; j < N; j++){
                if(grid[i][j] == 0){
                    left[i][j] = 0;
                }
                else{
                    if(j > 0 && grid[i][j-1] == 1){
                        left[i][j] = left[i][j-1] + 1;
                    }
                    else{
                        left[i][j] = 1;
                    }
                }

                int k = N-1-j;
                if(grid[i][k] == 0){
                    right[i][k] = 0;
                }
                else{
                    if(k < N-1 && grid[i][k+1] == 1){
                        right[i][k] = right[i][k+1] + 1;
                    }
                    else{
                        right[i][k] = 1;
                    }
                }
                
                if(grid[j][i] == 0){
                    up[j][i] = 0;
                }
                else{
                    if(j > 0 && grid[j-1][i] == 1){
                        up[j][i] = up[j-1][i] + 1;
                    }
                    else{
                        up[j][i] = 1;
                    }
                }

                int p = N-1-j;
                if(grid[p][i] == 0){
                    down[p][i] = 0;
                }
                else{
                    if(p < N-1 && grid[p+1][i] == 1){
                        down[p][i] = down[p+1][i] + 1;
                    }
                    else{
                        down[p][i] = 1;
                    }
                }
            }
        }
        int maxlen = 0;
        for(int r = 0; r < N; r++){
            for(int c = 0; c < N; c++){
                // cout<<"r="<<r<<"c="<<c<<":"<<"("<<left[r][c]<<","<<right[r][c]<<","<<up[r][c]<<","<<down[r][c]<<")"<<endl;
                int len = min(min(left[r][c],right[r][c]),min(up[r][c],down[r][c]));
                if(len > maxlen){
                    maxlen = len;
                }
            }
        }
        return maxlen;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章