目录
我在思考局部最優可能就是由後往前遍歷,倆倆比較假設後大於前,則不用變,前大於後,那就減掉前面的值,遍歷全部的數,但實際要怎麼解,帶馬上沒有想法。
看完之後發現跟我的想法相同,但更直接一點是把後面的數都變為9,很直接但很符合貪心的想法,基本上這樣做就不用擔心是否為單調遞增,並且取最大的單調遞增數並且透過flag紀錄i在哪裡開始要全部變成9,整體透過兩個不嵌套的迴圈解決這個問題。
另外轉成string也很棒,就是讓我們可以更直覺地去操控數字,因為如果沒有的話可能要花更多的代碼量去處理最後的結果。
在思考是不是貪心算法是找到葉子節點的父節點,並且之後都往跳兩層的父節點,這樣就可以找到全部了,但因為牽涉到二叉樹,並不是那麼了解到底怎麼處理。
貪心思路,後序遍歷,狀態劃分,四種情況
左右都有覆蓋
左右至少有一個無覆蓋
左右至少有一個有攝像頭
最後遍歷根節點無覆蓋,加攝像頭
看完之後覺得這題我只思考到貪心算法,但是後序遍歷,這個我需要去複習,狀態劃分以及四種情況我沒有思考到,但題目是有趣的,讓我對二叉樹以及貪心算法有個好玩的結合。
- class Solution {
- public:
- int monotoneIncreasingDigits(int n) {
- string number = to_string(n);
- int flag = number.size();
- for(int i = number.size() - 1; i > 0; i--) {
- if(number[i - 1] > number[i]) {
- flag = i;
- number[i - 1]--;
- }
- }
- for(int i = flag; i < number.size(); i++){
- number[i] = '9';
- }
- return stoi(number);
- }
- };
- /**
- * Definition for a binary tree node.
- * struct TreeNode {
- * int val;
- * TreeNode *left;
- * TreeNode *right;
- * TreeNode() : val(0), left(nullptr), right(nullptr) {}
- * TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
- * TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
- * };
- */
- class Solution {
- public:
- int result = 0;
- int traveral(TreeNode* cur) {
- if(cur == NULL) return 2; // 假設在葉子節點,需要選擇有覆蓋,那在葉子節點的父節點才會加上一個攝像頭
- int left = traveral(cur->left);
- int right = traveral(cur->right);
-
- if(left == 2 && right == 2) return 0; //左右都有覆蓋
- if(left == 0 || right == 0) { //左右至少有一個無覆蓋,則一定要一個攝像頭
- result++;
- return 1;
- }
- if(left == 1 || right == 1) return 2; // 左右至少有一個攝像頭,則return 2,因為代表該節點有被覆蓋到
- return -1;
- }
- int minCameraCover(TreeNode* root) {
- result = 0;
- if(traveral(root) == 0) { //最後一種情況,假設根節點左右節點都有覆蓋,那則要多加一個攝像頭
- result++;
- }
- return result;
-
- }
- };
回顧貪心算法,真的沒有固定的解法,可能有類似的套路,比如說重疊區間,或者是子序和,但整體還是一個思路上的轉換
貪心算法很簡單,主要體現在代碼上,但難點主要是思路上的轉換,說簡單也不簡單
沒有套路!沒有套路!沒有套路
真的是要讓自己的視野打開,多寫多練習,讓自己的腦袋瘋狂運轉,會越來越好的
其實任何情況下只要能推導出局部最優在堆疊到全局最優的題目都可以是貪心算法,但有些問題當然可以套用其他的解題技巧幫忙,貪心算法我認為就像是心法,它沒有招式但所以我們只能意會,很奇妙的章節。
題目分級,來源至代碼隨想錄
这里的题目如果没有接触过,其实是很难想到的,甚至接触过,也一时想不出来,所以题目不要做一遍,要多练!
今天的難點主要在監控二叉樹,單調遞增的數字難點主要在代碼,監控二叉樹則是需要考慮到多個面向的狀態,但其實真的很好玩,理解之後,寫代碼其實反而就是之前二叉樹章節的基礎,主要是思路不好想。
整體花大概兩個小時,貪心算法真的很奇妙,但理解之後真的很開心,感覺非常好玩。
● 今日学习的文章链接和视频链接
738.单调递增的数字
https://programmercarl.com/0738.单调递增的数字.html
968.监控二叉树
https://programmercarl.com/0968.监控二叉树.html
总结