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+篇,公眾號對話方塊回覆【資料結構與演算法】、【演算法】、【資料結構】中的任一關鍵詞,獲取系列文章合集。
以上就是全部內容,如果大家有什麼好的解法思路、建議或者其他問題,可以下方留言交流,點贊、留言、轉發就是對我最大的回報和支援!