日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

监控二叉树

發(fā)布時間:2024/4/18 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 监控二叉树 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

思路

這道題目首先要想,如何放置,才能讓攝像頭數(shù)最小呢?

然后我們發(fā)現(xiàn)題目示例中的攝像頭都沒有放在葉子節(jié)點上!

這是很重要的一個線索,攝像頭可以覆蓋上中下三層,如果把攝像頭放在葉子節(jié)點上,就浪費的一層的覆蓋。

所以把攝像頭放在葉子節(jié)點的父節(jié)點位置,才能充分利用攝像頭的覆蓋面積。

為什么不從頭結(jié)點開始看起呢,為啥要從葉子節(jié)點看呢?

因為頭結(jié)點放不放攝像頭也就省下一個攝像頭, 葉子節(jié)點放不放攝像頭省下了的攝像頭數(shù)量是指數(shù)級別的。

所以我們要從下往上看,局部最優(yōu):讓葉子節(jié)點的父節(jié)點安攝像頭,所用攝像頭最少,整體最優(yōu):全部攝像頭數(shù)量所用最少!

局部最優(yōu)推出全局最優(yōu),找不出反例,那么就按照貪心來!

此時,大體思路就是從下到上,先給葉子節(jié)點父節(jié)點放個攝像頭,然后隔兩個節(jié)點放一個攝像頭,直至到二叉樹頭結(jié)點。

此時這道題目還有兩個難點:

二叉樹的遍歷
如何隔兩個節(jié)點放一個攝像頭

確定遍歷順序

在二叉樹中如何從下向上推導(dǎo)呢?

可以使用后序遍歷也就是左右中的順序,這樣就可以在回溯的過程中從下到上進行推導(dǎo)了。

int traversal(TreeNode* cur) {// 空節(jié)點,該節(jié)點有覆蓋if (終止條件) return ;int left = traversal(cur->left); // 左int right = traversal(cur->right); // 右邏輯處理 // 中return ;}

以上代碼中我們?nèi)×俗蠛⒆雍陀液⒆拥姆祷刂?#xff0c;即left 和 right, 方便以后推導(dǎo)中間節(jié)點的狀態(tài)。

如何隔兩個節(jié)點放一個攝像頭

此時需要狀態(tài)轉(zhuǎn)移

這個狀態(tài)應(yīng)該如何轉(zhuǎn)移,我們首先看看每個節(jié)點可能有幾種狀態(tài):

1、本節(jié)點無覆蓋
2、本節(jié)點有攝像頭
3、本節(jié)點有覆蓋

我們分別有三個數(shù)字來表示:

0:本節(jié)點無覆蓋
1:本節(jié)點有攝像頭
2:本節(jié)點有覆蓋

注意:本節(jié)點無攝像頭,其實無攝像頭就是 無覆蓋 或者 有覆蓋的狀態(tài),所以一共還是三個狀態(tài)。

那么在遍歷樹的過程中,就會遇到空節(jié)點,那么問題來了,空節(jié)點究竟是哪一種狀態(tài)呢?空節(jié)點表示無覆蓋?表示有攝像頭?還是有覆蓋呢?

回歸本質(zhì),為了讓攝像頭數(shù)量最少,我們要盡量讓葉子節(jié)點的父節(jié)點安裝攝像頭,這樣才能攝像頭的數(shù)量最少。

那么空節(jié)點不能是無覆蓋的狀態(tài),這樣葉子節(jié)點就要放攝像頭了,空節(jié)點也不能是有攝像頭的狀態(tài),這樣葉子節(jié)點的父節(jié)點就沒有必要放攝像頭了,而是可以把攝像頭放在葉子節(jié)點的爺爺節(jié)點上。

所以空節(jié)點的狀態(tài)只能是有覆蓋,這樣就可以在葉子節(jié)點的父節(jié)點放攝像頭了

接下來就是遞推關(guān)系。

那么遞歸的終止條件應(yīng)該是遇到了空節(jié)點,此時應(yīng)該返回2(有覆蓋),原因上面已經(jīng)解釋過了。

// 空節(jié)點,該節(jié)點有覆蓋 if (cur == NULL) return 2;

單層邏輯處理

主要有如下四類情況:

情況1:左右節(jié)點都有覆蓋
左孩子有覆蓋,右孩子有覆蓋,那么此時中間節(jié)點應(yīng)該就是無覆蓋的狀態(tài)了。

// 左右節(jié)點都有覆蓋 if (left == 2 && right == 2) return 0;

情況2:左右節(jié)點至少有一個無覆蓋的情況

如果是以下情況,則中間節(jié)點(父節(jié)點)應(yīng)該放攝像頭:

left == 0 && right == 0 左右節(jié)點無覆蓋
left == 1 && right == 0 左節(jié)點有攝像頭,右節(jié)點無覆蓋
left == 0 && right == 1 左節(jié)點有無覆蓋,右節(jié)點攝像頭
left == 0 && right == 2 左節(jié)點無覆蓋,右節(jié)點覆蓋
left == 2 && right == 0 左節(jié)點覆蓋,右節(jié)點無覆蓋

這個不難理解,畢竟有一個孩子沒有覆蓋,父節(jié)點就應(yīng)該放攝像頭。

此時攝像頭的數(shù)量要加一,并且return 1,代表中間節(jié)點放攝像頭

if (left == 0 || right == 0) {result++;return 1; }

情況3:左右節(jié)點至少有一個有攝像頭

如果是以下情況,其實就是 左右孩子節(jié)點有一個有攝像頭了,那么其父節(jié)點就應(yīng)該是2(覆蓋的狀態(tài))

left == 1 && right == 2 左節(jié)點有攝像頭,右節(jié)點有覆蓋
left == 2 && right == 1 左節(jié)點有覆蓋,右節(jié)點有攝像頭
left == 1 && right == 1 左右節(jié)點都有攝像頭

if (left == 1 || right == 1) return 2;

情況4:頭結(jié)點沒有覆蓋

以上都處理完了,遞歸結(jié)束之后,可能頭結(jié)點 還有一個無覆蓋的情況,如圖:

所以遞歸結(jié)束之后,還要判斷根節(jié)點,如果沒有覆蓋,result++,代碼如下:

int minCameraCover(TreeNode* root) {result = 0;if (traversal(root) == 0) { // root 無覆蓋result++;}return result; }

最后的代碼

// 版本一 class Solution { private:int result;int traversal(TreeNode* cur) {// 空節(jié)點,該節(jié)點有覆蓋if (cur == NULL) return 2;int left = traversal(cur->left); // 左int right = traversal(cur->right); // 右// 情況1// 左右節(jié)點都有覆蓋if (left == 2 && right == 2) return 0;// 情況2// left == 0 && right == 0 左右節(jié)點無覆蓋// left == 1 && right == 0 左節(jié)點有攝像頭,右節(jié)點無覆蓋// left == 0 && right == 1 左節(jié)點有無覆蓋,右節(jié)點攝像頭// left == 0 && right == 2 左節(jié)點無覆蓋,右節(jié)點覆蓋// left == 2 && right == 0 左節(jié)點覆蓋,右節(jié)點無覆蓋if (left == 0 || right == 0) {result++;return 1;}// 情況3// left == 1 && right == 2 左節(jié)點有攝像頭,右節(jié)點有覆蓋// left == 2 && right == 1 左節(jié)點有覆蓋,右節(jié)點有攝像頭// left == 1 && right == 1 左右節(jié)點都有攝像頭// 其他情況前段代碼均已覆蓋if (left == 1 || right == 1) return 2;// 以上代碼我沒有使用else,主要是為了把各個分支條件展現(xiàn)出來,這樣代碼有助于讀者理解// 這個 return -1 邏輯不會走到這里。return -1;}public:int minCameraCover(TreeNode* root) {result = 0;// 情況4if (traversal(root) == 0) { // root 無覆蓋result++;}return result;} };

本題的難點首先是要想到貪心的思路,然后就是遍歷狀態(tài)推導(dǎo)

總結(jié)

以上是生活随笔為你收集整理的监控二叉树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。