本文为学习代码随想录 时所做的笔记,仅供学习参考,不做任何商业用途,若有侵权,请联系删除。
完全二叉树的节点个数
222.
完全二叉树的节点个数 - 力扣(LeetCode)
在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第
h 层,则该层包含 1~ 2^(h-1) 个节点。
完全二叉树只有两种情况,情况一:就是满二叉树,情况二:最后一层叶子节点没有满。
对于情况一,可以直接用 2^树深度 - 1
来计算,注意这里根节点深度为1。
对于情况二,分别递归左孩子,和右孩子,递归到某一深度一定会有左孩子或者右孩子为满二叉树,然后依然可以按照情况1来计算。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution {public : int countNodes (TreeNode* root) { if (root == nullptr ) return 0 ; TreeNode* left = root->left; TreeNode* right = root->right; int leftDepth = 0 , rightDepth = 0 ; while (left) { left = left->left; leftDepth++; } while (right) { right = right->right; rightDepth++; } if (leftDepth == rightDepth) { return (2 << leftDepth) - 1 ; } return countNodes (root->left) + countNodes (root->right) + 1 ; } };
平衡二叉树
110.
平衡二叉树 - 力扣(LeetCode)
二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数。
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数。
递归
明确递归函数的参数和返回值
1 2 int getHeight (TreeNode* node)
明确终止条件
1 2 3 if (node == NULL ) { return 0 ; }
明确单层递归的逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 int leftHeight = getHeight (node->left); if (leftHeight == -1 ) return -1 ;int rightHeight = getHeight (node->right); if (rightHeight == -1 ) return -1 ;int result;if (abs (leftHeight - rightHeight) > 1 ) { result = -1 ; } else { result = 1 + max (leftHeight, rightHeight); }return result;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution {public : int getHeight (TreeNode* node) { if (node == NULL ) { return 0 ; } int leftHeight = getHeight (node->left); if (leftHeight == -1 ) return -1 ; int rightHeight = getHeight (node->right); if (rightHeight == -1 ) return -1 ; return abs (leftHeight - rightHeight) > 1 ? -1 : 1 + max (leftHeight, rightHeight); } bool isBalanced (TreeNode* root) { return getHeight (root) == -1 ? false : true ; } };
二叉树的所有路径
257.
二叉树的所有路径 - 力扣(LeetCode)
递归
递归函数函数参数以及返回值
1 void traversal (TreeNode* cur, vector<int >& path, vector<string>& result)
确定递归终止条件
1 2 3 if (cur->left == NULL && cur->right == NULL ) { }
1 2 3 4 5 6 7 8 9 10 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); return ; }
确定单层递归逻辑
1 2 3 4 5 6 7 8 if (cur->left) { traversal (cur->left, path, result); path.pop_back (); }if (cur->right) { traversal (cur->right, path, result); path.pop_back (); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution {private : 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); return ; } if (cur->left) { traversal (cur->left, path, result); path.pop_back (); } if (cur->right) { traversal (cur->right, path, result); path.pop_back (); } }public : vector<string> binaryTreePaths (TreeNode* root) { vector<string> result; vector<int > path; if (root == NULL ) return result; traversal (root, path, result); return result; } };
左叶子之和
404.
左叶子之和 - 力扣(LeetCode)
递归法
确定递归函数的参数和返回值
1 int sumOfLeftLeaves (TreeNode* root)
确定终止条件
1 2 if (root == nullptr ) return 0 ;
确定单层递归的逻辑
1 2 3 4 5 6 7 if 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;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 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; } };
迭代法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : int sumOfLeftLeaves (TreeNode* root) { stack<TreeNode*> st; if (root == NULL ) return 0 ; st.push (root); int result = 0 ; while (!st.empty ()) { TreeNode* node = st.top (); st.pop (); if (node->left != NULL && node->left->left == NULL && node->left->right == NULL ) { result += node->left->val; } if (node->right) st.push (node->right); if (node->left) st.push (node->left); } return result; } };
找树左下角的值
513.
找树左下角的值 - 力扣(LeetCode)
递归
确定递归函数的参数和返回值
1 2 3 int maxDepth = INT_MIN; int result; void traversal (TreeNode* root, int depth)
确定终止条件
1 2 3 4 5 6 7 if (root->left == NULL && root->right == NULL ) { if (depth > maxDepth) { maxDepth = depth; result = root->val; } return ; }
确定单层循环
1 2 3 4 5 6 7 8 9 10 11 12 if (root->left) { depth++; traversal (root->left, depth); depth--; }if (root->right) { depth++; traversal (root->right, depth); depth--; }return ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class Solution {public : int maxDepth = INT_MIN; int result; void traversal (TreeNode* root, int depth) { if (root->left == NULL && root->right == NULL ) { if (depth > maxDepth) { maxDepth = depth; result = root->val; } return ; } if (root->left) { depth++; traversal (root->left, depth); depth--; } if (root->right) { depth++; traversal (root->right, depth); depth--; } return ; } int findBottomLeftValue (TreeNode* root) { traversal (root, 0 ); return result; } };
迭代法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Solution {public : int findBottomLeftValue (TreeNode* root) { queue<TreeNode*> que; if (root != NULL ) que.push (root); int result = 0 ; while (!que.empty ()) { int size = que.size (); for (int i = 0 ; i < size; i++) { TreeNode* node = que.front (); que.pop (); if (i == 0 ) result = node->val; if (node->left) que.push (node->left); if (node->right) que.push (node->right); } } return result; } };
路径总和
112. 路径总和 -
力扣(LeetCode)
递归
确定递归函数的参数和返回类型
1 bool traversal (treenode* cur, int count)
确定终止条件
1 2 if (!cur->left && !cur->right && count == 0 ) return true ; if (!cur->left && !cur->right) return false ;
确定单层递归的逻辑
1 2 3 4 5 6 7 8 9 10 11 if (cur->left) { count -= cur->left->val; if (traversal (cur->left, count)) return true ; count += cur->left->val; }if (cur->right) { count -= cur->right->val; if (traversal (cur->right, count)) return true ; count += cur->right->val; }return false ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution {private : bool traversal (TreeNode* cur, int count) { if (!cur->left && !cur->right && count == 0 ) return true ; if (!cur->left && !cur->right) return false ; if (cur->left) { count -= cur->left->val; if (traversal (cur->left, count)) return true ; count += cur->left->val; } if (cur->right) { count -= cur->right->val; if (traversal (cur->right, count)) return true ; count += cur->right->val; } return false ; }public : bool hasPathSum (TreeNode* root, int sum) { if (root == NULL ) return false ; return traversal (root, sum - root->val); } };
113. 路径总和 II
- 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class solution {private : vector<vector<int >> result; vector<int > path; void traversal (treenode* cur, int count) { if (!cur->left && !cur->right && count == 0 ) { result.push_back (path); return ; } if (!cur->left && !cur->right) return ; if (cur->left) { path.push_back (cur->left->val); count -= cur->left->val; traversal (cur->left, count); count += cur->left->val; path.pop_back (); } if (cur->right) { path.push_back (cur->right->val); count -= cur->right->val; traversal (cur->right, count); count += cur->right->val; path.pop_back (); } return ; }public : vector<vector<int >> pathsum (treenode* root, int sum) { result.clear (); path.clear (); if (root == null) return result; path.push_back (root->val); traversal (root, sum - root->val); return result; } };
从中序与后序遍历序列构造二叉树
106.
从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 TreeNode* traversal (vector<int >& inorder, vector<int >& postorder) { if (postorder.size () == 0 ) return NULL ; int rootValue = postorder[postorder.size () - 1 ]; TreeNode* root = new TreeNode (rootValue); if (postorder.size () == 1 ) return root; int delimiterIndex; for (delimiterIndex = 0 ; delimiterIndex < inorder.size (); delimiterIndex++) { if (inorder[delimiterIndex] == rootValue) break ; } root->left = traversal (中序左数组, 后序左数组); root->right = traversal (中序右数组, 后序右数组); return root; }
在切割的过程中会产生四个区间,把握不好不变量的话,一会左闭右开,一会左闭右闭,必然乱套!
中序数组相对比较好切,找到切割点(后序数组的最后一个元素)在中序数组的位置,然后切割,如下代码中我坚持左闭右开的原则:
1 2 3 4 5 6 7 8 9 10 int delimiterIndex;for (delimiterIndex = 0 ; delimiterIndex < inorder.size (); delimiterIndex++) { if (inorder[delimiterIndex] == rootValue) break ; }vector<int > leftInorder (inorder.begin(), inorder.begin() + delimiterIndex) ;vector<int > rightInorder (inorder.begin() + delimiterIndex + 1 , inorder.end() ) ;
接下来就要切割后序数组了。
首先后序数组的最后一个元素指定不能要了,这是切割点 也是
当前二叉树中间节点的元素,已经用了。
后序数组的切割点怎么找?
后序数组没有明确的切割元素来进行左右切割,不像中序数组有明确的切割点,切割点左右分开就可以了。
此时有一个很重的点,就是中序数组大小一定是和后序数组的大小相同的(这是必然)。
中序数组我们都切成了左中序数组和右中序数组了,那么后序数组就可以按照左中序数组的大小来切割,切成左后序数组和右后序数组。
1 2 3 4 5 6 7 postorder.resize (postorder.size () - 1 );vector<int > leftPostorder (postorder.begin(), postorder.begin() + leftInorder.size()) ;vector<int > rightPostorder (postorder.begin() + leftInorder.size(), postorder.end()) ;
此时,中序数组切成了左中序数组和右中序数组,后序数组切割成左后序数组和右后序数组。
接下来可以递归了,代码如下:
1 2 root->left = traversal (leftInorder, leftPostorder); root->right = traversal (rightInorder, rightPostorder);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Solution {private : TreeNode* traversal (vector<int >& inorder, vector<int >& postorder) { if (postorder.size () == 0 ) return NULL ; int rootValue = postorder[postorder.size () - 1 ]; TreeNode* root = new TreeNode (rootValue); if (postorder.size () == 1 ) return root; int delimiterIndex; for (delimiterIndex = 0 ; delimiterIndex < inorder.size (); delimiterIndex++) { if (inorder[delimiterIndex] == rootValue) break ; } vector<int > leftInorder (inorder.begin(), inorder.begin() + delimiterIndex) ; vector<int > rightInorder (inorder.begin() + delimiterIndex + 1 , inorder.end() ) ; postorder.resize (postorder.size () - 1 ); vector<int > leftPostorder (postorder.begin(), postorder.begin() + leftInorder.size()) ; vector<int > rightPostorder (postorder.begin() + leftInorder.size(), postorder.end()) ; root->left = traversal (leftInorder, leftPostorder); root->right = traversal (rightInorder, rightPostorder); return root; }public : TreeNode* buildTree (vector<int >& inorder, vector<int >& postorder) { if (inorder.size () == 0 || postorder.size () == 0 ) return NULL ; return traversal (inorder, postorder); } };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class Solution {private : TreeNode* traversal (vector<int >& inorder, int inorderBegin, int inorderEnd, vector<int >& postorder, int postorderBegin, int postorderEnd) { if (postorderBegin == postorderEnd) return NULL ; int rootValue = postorder[postorderEnd - 1 ]; TreeNode* root = new TreeNode (rootValue); if (postorderEnd - postorderBegin == 1 ) return root; int delimiterIndex; for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) { if (inorder[delimiterIndex] == rootValue) break ; } int leftInorderBegin = inorderBegin; int leftInorderEnd = delimiterIndex; int rightInorderBegin = delimiterIndex + 1 ; int rightInorderEnd = inorderEnd; int leftPostorderBegin = postorderBegin; int leftPostorderEnd = postorderBegin + delimiterIndex - inorderBegin; int rightPostorderBegin = postorderBegin + (delimiterIndex - inorderBegin); int rightPostorderEnd = postorderEnd - 1 ; root->left = traversal (inorder, leftInorderBegin, leftInorderEnd, postorder, leftPostorderBegin, leftPostorderEnd); root->right = traversal (inorder, rightInorderBegin, rightInorderEnd, postorder, rightPostorderBegin, rightPostorderEnd); return root; }public : TreeNode* buildTree (vector<int >& inorder, vector<int >& postorder) { if (inorder.size () == 0 || postorder.size () == 0 ) return NULL ; return traversal (inorder, 0 , inorder.size (), postorder, 0 , postorder.size ()); } };
从前序与中序遍历序列构造二叉树
105.
从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class Solution {private : TreeNode* traversal (vector<int >& inorder, int inorderBegin, int inorderEnd, vector<int >& preorder, int preorderBegin, int preorderEnd) { if (preorderBegin == preorderEnd) return NULL ; int rootValue = preorder[preorderBegin]; TreeNode* root = new TreeNode (rootValue); if (preorderEnd - preorderBegin == 1 ) return root; int delimiterIndex; for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) { if (inorder[delimiterIndex] == rootValue) break ; } int leftInorderBegin = inorderBegin; int leftInorderEnd = delimiterIndex; int rightInorderBegin = delimiterIndex + 1 ; int rightInorderEnd = inorderEnd; int leftPreorderBegin = preorderBegin + 1 ; int leftPreorderEnd = preorderBegin + 1 + delimiterIndex - inorderBegin; int rightPreorderBegin = preorderBegin + 1 + (delimiterIndex - inorderBegin); int rightPreorderEnd = preorderEnd; root->left = traversal (inorder, leftInorderBegin, leftInorderEnd, preorder, leftPreorderBegin, leftPreorderEnd); root->right = traversal (inorder, rightInorderBegin, rightInorderEnd, preorder, rightPreorderBegin, rightPreorderEnd); return root; }public : TreeNode* buildTree (vector<int >& preorder, vector<int >& inorder) { if (inorder.size () == 0 || preorder.size () == 0 ) return NULL ; return traversal (inorder, 0 , inorder.size (), preorder, 0 , preorder.size ()); } };
最大二叉树
654.
最大二叉树 - 力扣(LeetCode)
确定递归函数的参数和返回值
1 TreeNode* constructMaximumBinaryTree (vector<int >& nums)
确定终止条件
1 2 3 4 5 TreeNode* node = new TreeNode (0 );if (nums.size () == 1 ) { node->val = nums[0 ]; return node; }
确定单层递归的逻辑
先要找到数组中最大的值和对应的下标,
最大的值构造根节点,下标用来下一步分割数组。
1 2 3 4 5 6 7 8 9 10 int maxValue = 0 ;int maxValueIndex = 0 ;for (int i = 0 ; i < nums.size (); i++) { if (nums[i] > maxValue) { maxValue = nums[i]; maxValueIndex = i; } } TreeNode* node = new TreeNode (0 ); node->val = maxValue;
最大值所在的下标左区间 构造左子树
1 2 3 4 if (maxValueIndex > 0 ) { vector<int > newVec (nums.begin(), nums.begin() + maxValueIndex) ; node->left = constructMaximumBinaryTree (newVec); }
最大值所在的下标右区间构造右子树
1 2 3 4 if (maxValueIndex < (nums.size () - 1 )) { vector<int > newVec (nums.begin() + maxValueIndex + 1 , nums.end()) ; node->right = constructMaximumBinaryTree (newVec); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution {public : TreeNode* constructMaximumBinaryTree (vector<int >& nums) { TreeNode* node = new TreeNode (0 ); if (nums.size () == 1 ) { node->val = nums[0 ]; return node; } int maxValue = 0 ; int maxValueIndex = 0 ; for (int i = 0 ; i < nums.size (); i++) { if (nums[i] > maxValue) { maxValue = nums[i]; maxValueIndex = i; } } node->val = maxValue; if (maxValueIndex > 0 ) { vector<int > newVec (nums.begin(), nums.begin() + maxValueIndex) ; node->left = constructMaximumBinaryTree (newVec); } if (maxValueIndex < (nums.size () - 1 )) { vector<int > newVec (nums.begin() + maxValueIndex + 1 , nums.end()) ; node->right = constructMaximumBinaryTree (newVec); } return node; } };