代碼隨想錄算法訓練營|第十五天|层序遍历筆記&10題、226.翻转二叉树、101. 对称二叉树。刷题心得(c++)

目录

層序遍歷筆記

Code

迭代寫法

遞迴寫法

102.二叉树的层序遍历(opens new window) - 實作

思路

錯誤思路

正確思路

Code

錯誤代碼

正確代碼

107.二叉树的层次遍历II(opens new window) - 實作

思路

Code

199.二叉树的右视图(opens new window) - 實作

思路

錯誤思路

正確思路

Code

錯誤代碼

正確代碼

637.二叉树的层平均值(opens new window) - 實作

思路

Code

429.N叉树的层序遍历(opens new window) - 實作

思路

Code

515.在每个树行中找最大值(opens new window) - 實作

思路

Code

116.填充每个节点的下一个右侧节点指针(opens new window) - 實作

思路

錯誤思路

正確思路

Code

錯誤代碼

正確代碼

117.填充每个节点的下一个右侧节点指针II(opens new window) - 實作

思路

Code

104.二叉树的最大深度(opens new window) - 實作

思路

Code

111.二叉树的最小深度 - 實作

思路

Code

226.翻转二叉树 - 實作

思路

Code

101.对称二叉树 2 - 實作

思路

Code

總結

自己实现过程中遇到哪些困难

今日收获,记录一下自己的学习时长

相關資料

层序遍历

226.翻转二叉树

101. 对称二叉树


層序遍歷筆記

一層一層的遍歷二叉數,透過Queue先進先出的特性,以及紀錄目前的層數size大小,來記錄二叉樹的每層數值

整個過程就相識俄羅斯套娃的感覺,但這個不是一層套一個,而是一層可以套兩個,規則是每次只能拿走當下最大的

把大的拿走後下面有兩個中套娃,拿走其中一中個套娃發現下面還有兩個小套娃,但根據規則,要先把中的拿完,所以我們眼睛就知道目前下一層有兩個小的

再把最後一個中的拿走,發現下面有一個,所以小套娃目前總共有三個,代表下一次要拿三個

如果根據遞迴的想法,那就是

  1. 參數值是甚麼? root節點、result二維陣列 ( 二維陣列第一個部分是深度,第二個部分是廣度)
  2. 終止條件是甚麼? root == null
  3. 單遞迴的條件是甚麼? root→left & root right 放入queue當中。

Code

迭代寫法

class Solution {
public: 
	vector> levelOrder(TreeNode* root) {
		queue tree_que;
		if(root != NULL) tree_que.push(root);
		vector> results;
		while(!que.empty()) {
			int size = tree_que.size();
			vector vec;
			while(size--) {
				TreeNode* node = tree_que.front();
				tree_que.pop();
				vec.push_back(node->val);
				if(node->left) tree_que.push(node->left);
				if(node->right) tree_que.push(node->right);
			}
			results.push_back(vec);
			}
		return result;
	}

遞迴寫法

class Solution {
public: 
	void order(TreeNode* cur, vector>& results, int depth) {
		if(cur == NULL) return; //終止條件
		if(result.size() == depth) result.push_back(vector()); // 如果,result目前的一維陣列數量 == 目前的深度 ,那加一組一維陣列,這樣才會符合樹的結構
		result[depth].push_back(cur->val);
		order(cur->left, results, depth + 1);
		order(cur->right, results, depth + 1);
	}
	vector> levelOrder(TreeNode* root) {
		vector> results;
		int depth = 0;
		order(root, results, depth);
		return result;
	}

102.二叉树的层序遍历(opens new window) - 實作

思路

錯誤思路

  1. 建立
    1. 一個二維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是root == null || !queue.size()
  3. 單循環 root的下一層左右子樹加入到Queue當中

錯誤點,終止條件設錯,root並不會變化,也並不是!queue.size()

正確思路

  1. 建立
    1. 一個二維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 單循環 root的下一層左右子樹加入到Queue當中

Code

錯誤代碼

class Solution {
public:
    vector> levelOrder(TreeNode* root) {
        vector> result;
        queue que;
        if(root != NULL) que.push(root);
        while(root != NULL || !que.size()) {
            int size = que.size();
            vector tmp;
            while(size--) {
                TreeNode* node = que.front();
                que.pop();
                tmp.push_back(node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            result.push_back(tmp);
        }
        return result;
    }
};

正確代碼

class Solution {
public:
    vector> levelOrder(TreeNode* root) {
        vector> result;
        queue que;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            vector tmp;
            while(size--) {
                TreeNode* node = que.front();
                que.pop();
                tmp.push_back(node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            result.push_back(tmp);
        }
        return result;
    }
};

107.二叉树的层次遍历II(opens new window) - 實作

思路

  1. 建立
    1. 一個二維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 單循環 root的下一層左右子樹加入到Queue當中
  4. 最後reverse results

Code

class Solution {
public:
    vector> levelOrderBottom(TreeNode* root) {
        vector> result;
        queue que;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            vector tmp;
            while(size--) {
                TreeNode* node = que.front();
                que.pop();
                tmp.push_back(node->val);
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            result.push_back(tmp);
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

199.二叉树的右视图(opens new window) - 實作

思路

錯誤思路

  1. 建立
    1. 一個一維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 單循環 root的下一層右子樹加入到Queue當中

錯誤點:假設下一層只有一個數字,並且在左節點就會沒抓到,要改為去抓最右邊的數值,也就是每一層最後一個數值

正確思路

  1. 建立
    1. 一個一維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 單循環
    1. 假設遞迴到最後一個數值,加入result
    2. root的下一層左右子樹加入que

Code

錯誤代碼

class Solution {
public:
    vector rightSideView(TreeNode* root) {
        vector result;
        queue que;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            while(size--) {
                TreeNode* node = que.front();
                que.pop();
                result.push_back(node->val);
                if(node->right) que.push(node->right);
            }
        }
        return result;
    }
};

正確代碼

class Solution {
public:
    vector rightSideView(TreeNode* root) {
        vector result;
        queue que;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            int size = que.size();
						for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                if (i == (size - 1)) result.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return result;
    }
};

637.二叉树的层平均值(opens new window) - 實作

思路

  1. 建立
    1. 一個一維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. sum += node→val
  4. 假設i == size - 1 將數值平均後加入result
  5. 單循環 root的下一層左右子樹加入到Queue當中

Code

class Solution {
public:
    vector averageOfLevels(TreeNode* root) {
        vector result;
        queue que;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            double size = que.size();
            double sum = 0;
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                sum += node->val;                
                que.pop();
                if (i == (size - 1)) result.push_back(sum/size);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return result;
    }
};

429.N叉树的层序遍历(opens new window) - 實作

思路

  1. 建立
    1. 一個二維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 單循環 root的下一層child node加入到Queue當中

Code

class Solution {
public:
    vector> levelOrder(Node* root) {
        vector> result;
        queue que;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            vector tmp;
            while(size--) {
                Node* node = que.front();
                que.pop();
                tmp.push_back(node->val);
                for(int i = 0; i < node->children.size(); i++) {
                    if(node->children[i]) que.push(node->children[i]);
                }
            }
            result.push_back(tmp);
        }
        return result;
    }
};

515.在每个树行中找最大值(opens new window) - 實作

思路

  1. 建立
    1. 一個一維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 比較大小,假設數值較大則取代為max
  4. 假設i == size - 1 將將最大值加入result
  5. 單循環 root的下一層左右子樹加入到Queue當中

Code

class Solution {
public:
    vector largestValues(TreeNode* root) {
        vector result;
        queue que;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            int max = INT_MIN;
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                if(node->val > max) max = node->val;             
                que.pop();
                if (i == (size - 1)) result.push_back(max);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return result;
    }
};

116.填充每个节点的下一个右侧节点指针(opens new window) - 實作

思路

錯誤思路

  1. 建立
    1. 一個一維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 單循環
    1. 回圈大小設為size +1
    2. 假設遞迴到最後一個數值設定為null,加入result
    3. root的下一層左右子樹加入que

正確思路

  1. 建立
    1. 一個Queue儲存暫存結果
    2. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 循環
    1. 紀錄prenode 以及當下node
    2. 假設i=0 代表頭節點
    3. 假設不為零代表非頭節點
    4. 進行NODE的串接

Code

錯誤代碼

class Solution {
public:
    Node* connect(Node* root) {
        vector result;
        queue que;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            int size = que.size();
                for (int i = 0; i < size + 1; i++) {
                Node* node = que.front();
                que.pop();
                if (i == (size)) result.push_back(NULL);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return result;
    }
};

正確代碼

class Solution {
public:
    Node* connect(Node* root) {
     queue que;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            // vector vec;
            Node* nodePre;
            Node* node;
            for (int i = 0; i < size; i++) {
                if (i == 0) {
                    nodePre = que.front();
                    que.pop();
                    node = nodePre;
                } else {
                    node = que.front();
                    que.pop();
                    nodePre->next = node; 
                    nodePre = nodePre->next;
                }
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            nodePre->next = NULL; 
        }
        return root;
    }
};

117.填充每个节点的下一个右侧节点指针II(opens new window) - 實作

思路

  1. 建立
    1. 一個Queue儲存暫存結果
    2. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 循環
    1. 紀錄prenode 以及當下node
    2. 假設i=0 代表頭節點
    3. 假設不為零代表非頭節點
    4. 進行NODE的串接

Code

class Solution {
public:
    Node* connect(Node* root) {
     queue que;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            // vector vec;
            Node* nodePre;
            Node* node;
            for (int i = 0; i < size; i++) {
                if (i == 0) {
                    nodePre = que.front();
                    que.pop();
                    node = nodePre;
                } else {
                    node = que.front();
                    que.pop();
                    nodePre->next = node; 
                    nodePre = nodePre->next;
                }
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            nodePre->next = NULL; 
        }
        return root;
    }
};

104.二叉树的最大深度(opens new window) - 實作

思路

  1. 建立
    1. 一個二維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 單循環 root的下一層左右子樹加入到Queue當中
  4. 每次循環depth +1
  5. 最後reverse resul

Code

class Solution {
public:
    int maxDepth(TreeNode* root) {
                queue que;
				int depth = 0;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            while(size--) {
                TreeNode* node = que.front();
                que.pop();
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
            depth++;
        }
        return depth;
    }
};

111.二叉树的最小深度 - 實作

思路

  1. 建立
    1. 一個二維矩陣進行結果儲存與回傳
    2. 一個Queue儲存暫存結果
    3. 一個size,記錄每一層的數量
  2. 終止條件是!queue.empty()
  3. 單循環 root的下一層左右子樹加入到Queue當中
  4. 假設某一次左右子樹都為null,則直接return ++depth
  5. 每次循環depth +1

Code

class Solution {
public:
    int minDepth(TreeNode* root) {
        queue que;
        int depth = 0;
        if(root != NULL) que.push(root);
        while(!que.empty()) {
            int size = que.size();
            while(size--) {
                TreeNode* node = que.front();
                que.pop();
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
                if(!node->right && !node->left ) return ++depth;
            }
            depth++;
        }
        return depth;
    }
};

226.翻转二叉树 - 實作

思路

  1. 利用前序遍歷,遍歷二叉數
  2. 翻轉二叉樹的左右子樹。
  3. 將左右子樹放入stack

Code

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == NULL) return root;
        stack st;
        st.push(root);
        while(!st.empty()) {
            TreeNode* node = st.top();              // 中
            st.pop();
            swap(node->left, node->right);
            if(node->right) st.push(node->right);   // 右
            if(node->left) st.push(node->left);     // 左
        }
        return root;
    }
};

101.对称二叉树 2 - 實作

思路

  1. 因為是要比較root下面的左右子樹是否為對稱的,所以使用遞迴需要傳入左右子樹
  2. 假設不對稱,返回false,假設對稱返回true
  3. 終止條件為node為空,假設左節點為空右節點不為空,不對稱,假設右節點為空左節點不為空,不對稱,兩者為空對稱
  4. 單層遞迴的概念是,外比外內筆內,所以遞迴十,左樹放左節點,右樹放右節點,反之依然,左樹放右節點,右樹放左節點
  5. 判斷ouside and inside 是否相等

Code

總結

自己实现过程中遇到哪些困难

今天在實現的過程中,其實對於層序遍歷以及翻轉與對稱還需要花比較多時間去理解,一方面也是題目比較多,另一方面其實是時間的緣故,時間比較趕,但還是希望今天可以先碰一些,週六週日來做整理

今日收获,记录一下自己的学习时长

今天大概學了三小時左右,學了層序遍歷,其實整體還是蠻有趣的,雖然是模板,但是在不同的狀況下都有不同的玩法,其實真的蠻有趣的

相關資料

层序遍历

题目链接/文章讲解/视频讲解:https://programmercarl.com/0102.二叉树的层序遍历.html

226.翻转二叉树

题目链接/文章讲解/视频讲解:https://programmercarl.com/0226.翻转二叉树.html

101. 对称二叉树

题目链接/文章讲解/视频讲解:https://programmercarl.com/0101.对称二叉树.html

你可能感兴趣的:(算法,c++,leetcode,数据结构)