目录
讀題
110.平衡二叉树
自己看到题目的第一想法
看到完整題目,平衡二叉樹就是左右子樹的高度差不能超過一,假設超過一就不是,那其實跟求二叉樹的最小深度一樣,找出左右子樹的深度,之後進行比較,假設大於1 return false,小於等於1 return true;
看完代码随想录之后的想法
看完之後,我發現我對於高度跟深度有誤解,高度的話要用后序遍歷(下到上)來看,深度要用前序遍歷(上到下)來看,在求最大深度的時候,因為其實也可以看成求二叉樹的從葉子節點到根結點的高度,所以才可以使用前序遍歷。所以在遍歷的邏輯上以及思維上其實都進入了誤區,需要再找時間釐清二叉樹的想法
257. 二叉树的所有路径
自己看到题目的第一想法
看到第一眼是想我要怎麼給出結果,另外一個是我的左子樹要怎麼去跑,看得有點矇,直接看代碼隨想錄
看完代码随想录之后的想法
看完還是對回朔有點矇,這題代碼看完code之後有點理解思路,但是如果要更深入的解析,我需要花更久的時間才能做,但以目前的想法來說,因為卡哥有用一個取用地址的做法,在精簡版的代碼當中,path可以理解為區域變數,到了下一個遞迴就不見了,而完整版可以想像成全域變數,如果不pop,則異常,因為路徑仍在,我先寫完整版,協助我來理解這道問題
404.左叶子之和
自己看到题目的第一想法
看到之後感覺有點像所有路徑,一樣是到葉子節點,但是這邊要判斷說是不是左葉子節點,可能就要先去理解一下甚麼是左葉子節點了。
看完代码随想录之后的想法
看完之後,的確跟一般的二叉樹操作有所差異,但整體來說還是不難,只是我需要更多的時間來釐清這周二叉樹的部分。
110.平衡二叉树 - 實作
思路
錯誤思路
- get 左右子樹的深度
- 假設深度差超過一,則return false,否則return true;
錯誤點: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。我這只有比較root節點,並沒有去比較全部的節點
正確思路
- 用后序遍歷去找出右節點以及左節點的高度
- 假設右節點-左節點的絕對值高度大於一return -1,否則return 深度
- 主函數call 這個函數後,假設結果等於-1則return false,否則return ture;
Code
錯誤代碼
class Solution {
public:
int getdepth(TreeNode* cur) {
if(cur == NULL) return 1;
int leftdepth = getdepth(cur->left);
int rightdepth = getdepth(cur->right);
return 1 + max(leftdepth, rightdepth);
}
bool isBalanced(TreeNode* root) {
if(root == NULL) return 1;
int rightdepth = getdepth(root->right);
int leftdepth = getdepth(root->left);
int gap = 0;
if(rightdepth > leftdepth) gap = rightdepth - leftdepth;
else gap = leftdepth - rightdepth;
return gap <= 1 ? true:false;
}
};
正確代碼
class Solution {
public:
int gethight(TreeNode* cur) {
if(cur == NULL) return 0;
int lefthight = getdepth(cur->left);
if(lefthight == -1) return -1;
int righthight = getdepth(cur->right);
if(righthight == -1) return -1;
int result = 0;
if(abs(lefthight - righthight) > 1) result = -1;
else result = 1 + max(lefthight,righthight);
return result;
}
bool isBalanced(TreeNode* root) {
return gethight(root) == -1 ? false : true;
}
};
257. 二叉树的所有路径 - 實作
思路
- 定義一個函數,傳入root、紀錄回朔過程的path以及result
- 將當前節點加到路徑當中(因為假設當前節點就是葉子節點,那如果終止邏輯在前,則會沒有將當前節點加入)
- 終止邏輯是當root在葉子節點的時候,所以是左右子樹為空的狀況
- 處理路徑回朔的過程
- 確定單層遞迴邏輯
- 假設左子點不為空遞迴左子點
- pop path
- 假設右子點不為空遞迴右子點
- pop path
- 假設左子點不為空遞迴左子點
Code
class Solution {
public:
void traversal(TreeNode* cur, vector<int>&path, vector<string>& result) {
path.push_back(cur->val);
if(cur->left == NULL && cur->right ==NULL) {
string sPath;
for(int i = 0; i < path.size()-1; i++) {
sPath += to_string(path[i]);
sPath += "->";
}
sPath += to_string(path[path.size() - 1]);
result.push_back(sPath);
}
if(cur->left) {
traversal(cur->left, path, result);
path.pop_back();
}
if(cur->right) {
traversal(cur->right, path, result);
path.pop_back();
}
}
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> result;
vector<int> path;
if(root == NULL) return result;
traversal(root, path, result);
return result;
}
};
思考
寫的過程中,不斷的去思考,突然理解了回朔的過程,path是vector,底層是dequeue,在這個過程中,假設我一直走左子樹,那我到底的時候,我的path就是在左子樹的第一個葉子節點那我回朔的時候就要path就要pop一個葉子,假設有右節點下一個就會進到右節點,右節點結束之後,就會跳出,之後又把path給pop出來,這樣就達到回朔的目的了。
404.左叶子之和 - 實作
思路
- 將root傳入,並回傳int → 回傳左右子樹的左葉子的和
- 終止條件有兩個,當root為空以及當在葉子節點的時候
- 單層遞迴邏輯
- 假設左子樹的左孩子的左右子樹等於Null代表左子樹的左孩子為葉子節點將value帶入leftValue
- right value遞迴
- sum = leftvalue + right value
- return sum
Code
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if(root == NULL) return 0;
if(root->left == NULL && root->right == NULL) return 0;
int leftValue = sumOfLeftLeaves(root->left);
if(root->left && !root->left->left && !root->left->right) {
leftValue = root->left->val;
}
int rightValue = sumOfLeftLeaves(root->right);
int sum = leftValue + rightValue;
return sum;
}
};
總結
自己实现过程中遇到哪些困难
今天在實現的過程中發現自己對於二叉樹的知識還是不足,經驗上也是,所以在看到這三題的時候,其實很多時候是不清楚的,現在還需要再花時間理解
今日收获,记录一下自己的学习时长
今天至少知道自己對於前中後序的用法還是不太清楚以及高度與深度的求法,讓我可以在接下來兩天的假期中好好去理解
相關資料
● 今日学习的文章链接和视频链接
110.平衡二叉树
题目链接/文章讲解/视频讲解:https://programmercarl.com/0110.平衡二叉树.html
257. 二叉树的所有路径
题目链接/文章讲解/视频讲解:https://programmercarl.com/0257.二叉树的所有路径.html
404.左叶子之和
题目链接/文章讲解/视频讲解:https://programmercarl.com/0404.左叶子之和.html