1. 程式人生 > >LeetCode演算法題-Construct Quad Tree(Java實現)

LeetCode演算法題-Construct Quad Tree(Java實現)

這是悅樂書的第224次更新,第237篇原創

01 看題和準備

今天介紹的是LeetCode演算法題中Easy級別的第91題(順位題號是427)。我們想使用四叉樹來儲存N×N布林網格。網格中的每個單元格只能是true或false。根節點表示整個網格。對於每個節點,它將被細分為四個子節點,直到它所代表的區域中的值都相同。

每個節點都有另外兩個布林屬性:isLeaf和val。當且僅當節點是葉節點時,isLeaf才為真。葉節點的val屬性包含它所代表的區域的值。您的任務是使用四叉樹來表示給定的網格。例如:

給定下面的8 x 8網格,我們想構建相應的四叉樹:

它可以根據上面的定義進行劃分:

相應的四叉樹應如下,其中每個節點表示為(isLeaf,val)對。
對於非葉節點,val可以是任意的,因此它表示為*。


注意:

  • N小於1000並保證為2的冪。

  • 如果您想了解有關四叉樹的更多資訊,可以參考其維基。

02 理解題意

題目中所說的葉節點,是指值相同的一片區域,如上圖被分成64個小格子的第三張圖,左上、左下和右下都表示了一片值相等的區域,左上左下都表示了16個1,右下表示了16個0,而右上中的16個格子,其中有8個0和8個1,只能再進行四等分,才能分別表示四個值相同的區域,所以右上區域不是葉節點,它的isLeaf屬性就為false。可以看到最後這張圖,根節點不是葉節點,所以其isLeaf也為false,而其他葉節點的isLeaf都為true。

03 第一種解法

題目給的引數是一個二維陣列,可以將其想象為一個N×N的格子,其索引就是對應位置的座標,只要從根節點開始,遇到和根節點值不一樣的座標,就需要進行等分操作,也就是從一個新的N/2×N/2格子開始,再從根節點開始判斷。因此可以藉助遞迴的方法,只需要兩個從0開始的索引,以及二維陣列的長度即可(此引數做再分用)。

/*
// Definition for a QuadTree node.
class Node {
    public boolean val;
    public boolean isLeaf;
    public Node topLeft;
    public Node topRight;
    public Node bottomLeft;
    public Node bottomRight;

    public Node() {}

    public Node(boolean _val,boolean _isLeaf,Node _topLeft,Node _topRight,Node _bottomLeft,Node _bottomRight) {
        val = _val;
        isLeaf = _isLeaf;
        topLeft = _topLeft;
        topRight = _topRight;
        bottomLeft = _bottomLeft;
        bottomRight = _bottomRight;
    }
};
*/
class Solution {
    public Node construct(int[][] grid) {
        return build(0, 0, grid.length, grid);
    }

    Node build(int x, int y, int len, int[][] grid){
        if (len < 0) {
            return null;
        }
        for (int i = x; i < x+len; ++i) {
            for (int j = y; j < y+len; ++j) {
                if (grid[i][j] != grid[x][y]) {
                    return new Node(true, false,
                           build(x, y, len/2, grid),
                           build(x, y + len/2, len/2, grid),
                           build(x + len/2, y, len/2, grid),
                           build(x + len/2, y + len/2, len/2, grid));
                }
            }
        }
        return new Node(grid[x][y] == 1, true, null, null, null, null);
    }
}


04 第二種解法

第一種解法是隻用兩個點來定位區間,此解法利用四個點來定位區間,但是思路都是一樣的。

/*
// Definition for a QuadTree node.
class Node {
    public boolean val;
    public boolean isLeaf;
    public Node topLeft;
    public Node topRight;
    public Node bottomLeft;
    public Node bottomRight;

    public Node() {}

    public Node(boolean _val,boolean _isLeaf,Node _topLeft,Node _topRight,Node _bottomLeft,Node _bottomRight) {
        val = _val;
        isLeaf = _isLeaf;
        topLeft = _topLeft;
        topRight = _topRight;
        bottomLeft = _bottomLeft;
        bottomRight = _bottomRight;
    }
};
*/
class Solution {
    public Node construct2(int[][] g) {
        return build(0, 0, g.length - 1, g.length - 1, g);
    }

    Node build(int r1, int c1, int r2, int c2, int[][] g) {
        if (r1 > r2 || c1 > c2) {
            return null;
        }
        boolean isLeaf = true;
        int val = g[r1][c1];
        for (int i = r1; i <= r2; i++)
            for (int j = c1; j <= c2; j++)
                if (g[i][j] != val) {
                    isLeaf = false;
                    break;
                }
        if (isLeaf) {
            return new Node(val == 1, true, null, null, null, null);
        }
        int rowMid = (r1 + r2)/2; 
        int colMid = (c1 + c2)/2;
        return new Node(false, false, 
                build(r1, c1, rowMid, colMid, g), 
                build(r1, colMid + 1, rowMid, c2, g), 
                build(rowMid + 1, c1, r2, colMid, g), 
                build(rowMid + 1, colMid + 1, r2, c2, g) 
        );
    }
}


05 小結

演算法專題目前已連續日更超過兩個月,演算法題文章91+篇,公眾號對話方塊回覆【資料結構與演算法】、【演算法】、【資料結構】中的任一關鍵詞,獲取系列文章合集。

以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!