764. Largest Plus Sign

Description

In a 2D grid from (0, 0) to (N-1, N-1), every cell contains a 1, except those cells in the given list mines which are 0. What is the largest axis-aligned plus sign of 1s contained in the grid? Return the order of the plus sign. If there is none, return 0.

An "axis-aligned plus sign of 1s of order k" has some center grid[x][y] = 1 along with 4 arms of length k-1 going up, down, left, and right, and made of 1s. This is demonstrated in the diagrams below. Note that there could be 0s or 1s beyond the arms of the plus sign, only the relevant area of the plus sign is checked for 1s.

Examples of Axis-Aligned Plus Signs of Order k:

Order 1:
000
010
000

Order 2:
00000
00100
01110
00100
00000

Order 3:
0000000
0001000
0001000
0111110
0001000
0001000
0000000

Example 1:

Input: N = 5, mines = [[4, 2]]
Output: 2
Explanation:
11111
11111
11111
11111
11011
In the above grid, the largest plus sign can only be order 2. One of them is marked in bold.

Example 2:

Input: N = 2, mines = []
Output: 1
Explanation:
There is no plus sign of order 2, but there is of order 1.

Example 3:

Input: N = 1, mines = [[0, 0]]
Output: 0
Explanation:
There is no plus sign, so return 0.

Note:

  1. N will be an integer in the range [1, 500].
  2. mines will have length at most 5000.
  3. mines[i] will be length 2 and consist of integers in the range [0, N-1].
  4. (Additionally, programs submitted in C, C++, or C# will be judged with a slightly smaller time limit.)

Solution

題目好長,翻譯過來就是在一個01稀疏矩陣中找由連續(xù)1組成的最大的十字架(十字架每條邊長度相等)。

3D-DP + HashSet, time O(n ^ 2), space O(n ^ 2)

三維DP,int[][][] dp = new int[n + 2][n + 2][4],z維度表示四個方向。
注意對于坐標(i, j)來說,它依賴于上下左右四個方向的dp值,所以還需要從后往前遍歷。

由于mines是一組坐標,可以將其轉(zhuǎn)換成一維存在HashSet中,方便查詢。

class Solution {
    // up, left, down, right
    public static final int[][] DIRECTIONS = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
    
    public int orderOfLargestPlusSign(int n, int[][] mines) {
        int[][][] dp = new int[n + 2][n + 2][4];
        Set<Integer> mineSet = new HashSet<>();
        for (int[] mine : mines) {
            mineSet.add(getIndex(mine[0], mine[1], n));
        }
        // traverse from up to bottom, left to right
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                if (mineSet.contains(getIndex(i, j, n))) {
                    continue;
                }     
                
                for (int k = 0; k < 2; ++k) {
                    dp[i + 1][j + 1][k] 
                         = 1 + dp[i + 1 + DIRECTIONS[k][0]][j + 1 + DIRECTIONS[k][1]][k];  
                }
            }
        }
        // traverse from bottom to up, right to left
        int max = 0;
        for (int i = n - 1; i >= 0; --i) {
            for (int j = n - 1; j >= 0; --j) {
                if (mineSet.contains(getIndex(i, j, n))) {
                    continue;
                }     
                
                for (int k = 2; k < 4; ++k) {
                    dp[i + 1][j + 1][k] 
                         = 1 + dp[i + 1 + DIRECTIONS[k][0]][j + 1 + DIRECTIONS[k][1]][k];  
                }
                // update max when 4 directions are done
                max = Math.max(min(dp[i + 1][j + 1]), max);
            }
        }
        
        return max;
    }
    
    public int getIndex(int i, int j, int n) {
        return i * n + j;
    }
    
    public int min(int[] a) {
        int min = Integer.MAX_VALUE;
        for (int n : a) {
            min = Math.min(n, min);
        }
        return min;
    }
}

2D-DP + HashSet, time O(n ^ 2), space O(n ^ 2)

下面這種寫法更清晰一點,推薦。

class Solution {
    public int orderOfLargestPlusSign(int n, int[][] mines) {
        int[][] dp = new int[n][n];
        Set<Integer> mineSet = new HashSet<>();
        for (int[] mine : mines) {
            mineSet.add(getIndex(mine[0], mine[1], n));
        }

        for (int i = 0; i < n; ++i) {
            int count = 0;
            for (int j = 0; j < n; ++j) {
                count = mineSet.contains(getIndex(i, j, n)) ? 0 : count + 1;
                dp[i][j] = count;
            }
            
            count = 0;
            for (int j = n - 1; j >= 0; --j) {
                count = mineSet.contains(getIndex(i, j, n)) ? 0 : count + 1;
                dp[i][j] = Math.min(count, dp[i][j]);
            }
        }
        
        int max = 0;
        
        for (int j = 0; j < n; ++j) {
            int count = 0;
            for (int i = 0; i < n; ++i) {
                count = mineSet.contains(getIndex(i, j, n)) ? 0 : count + 1;
                dp[i][j] = Math.min(count, dp[i][j]);
            }
            
            count = 0;
            for (int i = n - 1; i >= 0; --i) {
                count = mineSet.contains(getIndex(i, j, n)) ? 0 : count + 1;
                dp[i][j] = Math.min(count, dp[i][j]);
                max = Math.max(dp[i][j], max);
            }
        }
        
        return max;
    }
    
    public int getIndex(int i, int j, int n) {
        return i * n + j;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,861評論 0 10
  • 1新烏鴉喝水 有一只烏鴉,在無望的天空飛翔。飛著飛著, 忽然覺得口渴,于是找到了一個瓶子,看到里面有一點水。它想效...
    一只羊1237閱讀 435評論 0 0
  • 微信的使用場景越來越多,不管是在生活中工作上都要用到微信,微信語音確實給微信提供了很大的便利,使得很多不會打字或者...
    陳進東閱讀 654評論 0 0
  • 昨晚睡前又是滿身紅圈。大師兄說睡一覺就好了。 今早睜眼9點多,賴床。然后看書???1點起床吃飯。 吃飯的時候和一個...
    觸角_閱讀 350評論 3 1
  • 什么時候開始,可以不用因為買了件襯衫要200就心疼一下就好了。
    云來書信閱讀 126評論 0 0

友情鏈接更多精彩內(nèi)容