目錄
- 題目連結:738. 單調遞增的數字-中等
- 題目連結:968. 監控二叉樹-困難
題目連結:738. 單調遞增的數字-中等
題目描述:
當且僅當每個相鄰位數上的數字 x
和 y
滿足 x <= y
時,我們稱這個整數是單調遞增的。
給定一個整數 n
,返回 小於或等於 n
的最大數字,且數字呈 單調遞增 。
示例 1:
輸入: n = 10
輸出: 9
示例 2:
輸入: n = 1234
輸出: 1234
示例 3:
輸入: n = 332
輸出: 299
提示:
0 <= n <= 10^9
此題需要從後往前遍歷,當遇到前一位比該位大的時候,將前一位數字減一,向前繼續遍歷,直到最大位(即第1位),記錄下需要改的最大位(即迴圈裡後面遍歷到的),從這一位開始後面的都修改為9,得到的就是結果。
程式碼如下:
// 時間複雜度:O(n),n 為數字長度
// 空間複雜度:O(n),需要一個字串,轉化為字串操作更方便
class Solution {
public:
int monotoneIncreasingDigits(int n) {
string str = to_string(n);
int flag = str.size();
for (int i = str.size() - 1; i > 0; --i) {
if (str[i - 1] > str[i]) {
--str[i - 1];
flag = i;
}
}
for (int i = flag; i < str.size(); ++i) {
str[i] = '9';
}
return stoi(str);
}
};
題目連結:968. 監控二叉樹-困難
題目描述:
給定一個二叉樹,我們在樹的節點上安裝攝像頭。
節點上的每個攝影頭都可以監視其父物件、自身及其直接子物件。
計算監控樹的所有節點所需的最小攝像頭數量。
示例 1:
輸入:[0,0,null,0,0]
輸出:1
解釋:如圖所示,一臺攝像頭足以監控所有節點。
示例 2:
輸入:[0,0,null,0,null,0,null,null,0]
輸出:2
解釋:需要至少兩個攝像頭來監視樹的所有節點。 上圖顯示了攝像頭放置的有效位置之一。
提示:
- 給定樹的節點數的範圍是
[1, 1000]
。 - 每個節點的值都是 0。
主要有如下四類情況:
- 情況1:左右節點都有覆蓋
左孩子有覆蓋,右孩子有覆蓋,那麼此時中間節點應該就是無覆蓋的狀態了。
- 情況2:左右節點至少有一個無覆蓋的情況
如果是以下情況,則中間節點(父節點)應該放攝像頭
- 情況3:左右節點至少有一個有攝像頭
如果是以下情況,其實就是 左右孩子節點有一個有攝像頭了,那麼其父節點就應該是2(覆蓋的狀態)
- 情況4:頭結點沒有覆蓋
以上都處理完了,遞迴結束之後,可能頭結點 還有一個無覆蓋的情況
程式碼如下:
// 時間複雜度: O(n),需要遍歷二叉樹上的每個節點
// 空間複雜度: O(n)
class Solution {
private:
int result;
int traversal(TreeNode* cur) {
// 空節點,該節點有覆蓋
if (cur == NULL) return 2;
int left = traversal(cur->left); // 左
int right = traversal(cur->right); // 右
// 情況1
// 左右節點都有覆蓋
if (left == 2 && right == 2) return 0;
// 情況2
// left == 0 && right == 0 左右節點無覆蓋
// left == 1 && right == 0 左節點有攝像頭,右節點無覆蓋
// left == 0 && right == 1 左節點有無覆蓋,右節點攝像頭
// left == 0 && right == 2 左節點無覆蓋,右節點覆蓋
// left == 2 && right == 0 左節點覆蓋,右節點無覆蓋
if (left == 0 || right == 0) {
result++;
return 1;
}
// 情況3
// left == 1 && right == 2 左節點有攝像頭,右節點有覆蓋
// left == 2 && right == 1 左節點有覆蓋,右節點有攝像頭
// left == 1 && right == 1 左右節點都有攝像頭
// 其他情況前段程式碼均已覆蓋
if (left == 1 || right == 1) return 2;
// 以上程式碼我沒有使用else,主要是為了把各個分支條件展現出來,這樣程式碼有助於讀者理解
// 這個 return -1 邏輯不會走到這裡。
return -1;
}
public:
int minCameraCover(TreeNode* root) {
result = 0;
// 情況4
if (traversal(root) == 0) { // root 無覆蓋
result++;
}
return result;
}
};
精簡如下:
class Solution {
private:
int result;
int traversal(TreeNode* cur) {
if (cur == NULL) return 2;
int left = traversal(cur->left); // 左
int right = traversal(cur->right); // 右
if (left == 2 && right == 2) return 0;
else if (left == 0 || right == 0) {
result++;
return 1;
} else return 2;
}
public:
int minCameraCover(TreeNode* root) {
result = 0;
if (traversal(root) == 0) { // root 無覆蓋
result++;
}
return result;
}
};