二叉树
1、求根节点到叶子节点数字之和
129. 求根节点到叶节点数字之和 - 力扣(LeetCode)

我的解法:使用中序遍历,为什么使用中序遍历?
第一、直观印象,回溯算法我惯用中序遍历
第二、对于本题,我没有记录访问过的路径 vector<int> path,我是在叶子节点处对数值进行累加的,所以必须要用中序遍历的方式。
废话不多说,C++完整代码如下:
/*** 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 sum = 0; // 结果void traversal(TreeNode* root, int curSum){// 中if(root->left == nullptr && root->right == nullptr){sum += curSum;return;}// 左if(root->left) traversal(root->left, (curSum * 10 + root->left->val)); // 回溯,藏在了参数里// 右if(root->right) traversal(root->right, curSum * 10 + root->right->val); // 回溯,藏在了参数里return;}int sumNumbers(TreeNode* root) {traversal(root, root->val);return sum;}};
上面的代码,需要对回溯有一定的理解,看不懂的话可以看下面的代码:
/*** 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;vector<int> path;// 自定义函数,将vector转成intint vectorToInt(const vector<int>& path){int sum = 0;for(int i = 0; i < path.size(); i++){sum = sum * 10 + path[i];}return sum;}// 自定义函数,实现对二叉树的回溯void backtracking(TreeNode* root){// 中if(!root->left && !root->right){result += vectorToInt(path);return;}// 左if(root->left){path.push_back(root->left->val); // 处理节点backtracking(root->left); // 递归path.pop_back(); // 回溯,撤销上一步的操作}// 右if(root->right){path.push_back(root->right->val); // 处理节点backtracking(root->right); // 递归path.pop_back(); // 回溯,撤销上一步的操作}return;}int sumNumbers(TreeNode* root) {if(root == nullptr) return 0;path.clear();result = 0;path.push_back(root->val);backtracking(root);return result;}};
Java代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/class Solution {int result = 0;public void traversal(TreeNode root, int curSum){// 中,处理节点if(root.left == null && root.right == null){result += curSum;return;}// 左(空节点不递归)if(root.left != null) traversal(root.left, curSum * 10 + root.left.val);// 右(空姐点不递归)if(root.right != null) traversal(root.right, curSum * 10 + root.right.val);return;}public int sumNumbers(TreeNode root) {traversal(root, root.val);return result;}}
2、路径总和 II
/*** 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:vector<vector<int>> result;vector<int> path;void backtracking(TreeNode* root, int targetSum){if(!root->left && !root->right){if(getPathSum(path) == targetSum){result.push_back(path);return;}}if(root->left){path.push_back(root->left->val);backtracking(root->left, targetSum);path.pop_back();}if(root->right){path.push_back(root->right->val);backtracking(root->right, targetSum);path.pop_back();}return;}int getPathSum(vector<int>& path){int sum = 0;for(int i = 0; i < path.size(); i++){sum += path[i];}return sum;}vector<vector<int>> pathSum(TreeNode* root, int targetSum) {result.clear();path.clear();if(root == nullptr) return result;path.push_back(root->val);backtracking(root, targetSum);return result;}};
Java代码
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/class Solution {List<List<Integer>> result = new ArrayList<>();List<Integer> path = new ArrayList<>();// 自定义函数,回溯二叉树public void backtracking(TreeNode root, int targetSum){if(root.left == null && root.right == null){if(getPathSum(path) == targetSum){result.add(new ArrayList<>(path));}return;}if(root.left != null){path.add(root.left.val); // 添加元素backtracking(root.left, targetSum); // 递归path.remove(path.size() - 1); // 回溯}if(root.right != null){path.add(root.right.val);backtracking(root.right, targetSum);path.remove(path.size() - 1);}}// 自定义函数,对path求和public int getPathSum(List<Integer> path){int sum = 0;for(int i = 0; i < path.size(); i++){sum += path.get(i);}return sum;}public List<List<Integer>> pathSum(TreeNode root, int targetSum) {// result.removeAll(result);// path.removeAll(path);if(root == null) return result;path.add(root.val);backtracking(root, targetSum);return result;}}
3、路径总和
/*** 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:bool backtracking(TreeNode* root, int count){if(!root->left && !root->right && count == 0) return true; // 遇到叶子节点,并且计数为0if(!root->left && !root->right) return false; // 遇到叶子节点直接返回if(root->left){if(backtracking(root->left, count - root->left->val)){return true;}}if(root->right){if(backtracking(root->right, count - root->right->val)){return true;}}return false;}bool hasPathSum(TreeNode* root, int targetSum) {if(root == nullptr) return false;return backtracking(root, targetSum - root->val);}};
Java代码
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/class Solution {boolean flag = false;public void backtracking(TreeNode root, int targetSum){if(root.left == null && root.right == null){if(targetSum == 0){flag = true;}}if(root.left != null){backtracking(root.left, targetSum - root.left.val); // 回溯}if(root.right != null){backtracking(root.right, targetSum - root.right.val);}}public boolean hasPathSum(TreeNode root, int targetSum) {if(root == null) return false;backtracking(root, targetSum - root.val);return flag;}}
4、验证二叉搜索树
递归法
/*** 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:vector<int> vec;void backtracking(TreeNode* root){if(root == nullptr){return;}backtracking(root->left);vec.push_back(root->val);backtracking(root->right);}bool isValidBST(TreeNode* root) {backtracking(root);for(int i = 0; i < vec.size() - 1; i++){if(vec[i] >= vec[i + 1]) return false;}return true;}};
迭代法
方法一:
这道题可以使用 long long maxVal = LONG_MIN; 来记录上一次出现的最大的值,如果当前节点的值小于这个 maxVal,说明这不是一颗二叉搜索树。
代码如下:
/*** 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:bool isValidBST(TreeNode* root) {stack<TreeNode*> st;st.push(root);long long maxVal = LONG_MIN;while(!st.empty()){TreeNode* cur = st.top();if(cur != nullptr){st.pop();if(cur->right) st.push(cur->right); // 右st.push(cur); // 中st.push(nullptr);if(cur->left) st.push(cur->left); // 左}else{st.pop(); // 弹出标记的节点 nullptrif(maxVal >= st.top()->val) return false;maxVal = maxVal > st.top()->val ? maxVal : st.top()->val; // 更新maxVal的值st.pop(); // 弹出当前节点}}return true;}};
但是这种解法仍然存在不足,如果二叉树节点的数值最大比 long long 类型还大呢?这时候就溢出啦。
方法二:
使用pre 指针,指向上一次访问的节点。
/*** 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:bool isValidBST(TreeNode* root) {stack<TreeNode*> st;st.push(root);TreeNode* pre = nullptr;while(!st.empty()){TreeNode* cur = st.top();if(cur != nullptr){st.pop();if(cur->right) st.push(cur->right); // 右st.push(cur); // 中st.push(nullptr); // 插入标志if(cur->left) st.push(cur->left); // 左}else{st.pop(); // 弹出标记的节点 nullptrif(pre != nullptr && pre->val >= st.top()->val){return false;}pre = st.top(); // 记录前一个节点值st.pop();}}return true;}};
Java代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/class Solution {List<Integer> list = new ArrayList<>();void traversal(TreeNode root){if(root == null){return;}traversal(root.left);list.add(root.val);traversal(root.right);}public boolean isValidBST(TreeNode root) {list.clear();traversal(root);for(int i = 0; i < list.size() - 1; i++){if(list.get(i) >= list.get(i + 1)) return false;}return true;}}
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/class Solution {public boolean isValidBST(TreeNode root) {Stack<TreeNode> st = new Stack<>();st.push(root);TreeNode pre = null;while(!st.isEmpty()){TreeNode cur = st.peek();if(cur != null){st.pop();if(cur.right != null) st.push(cur.right); // 右st.push(cur); // 中st.push(null); // 插入标志if(cur.left != null) st.push(cur.left); // 左} else{st.pop();if(pre != null && pre.val >= st.peek().val){return false;}pre = st.peek();st.pop();}}return true;}}
5、将有序数组转为二叉搜索树
108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)

题目中说要转换为一棵高度平衡二叉搜索树。这和转换为一棵普通二叉搜索树有什么差别呢?
其实这里不用强调平衡二叉搜索树,数组构造二叉树,构成平衡树是自然而然的事情,因为大家默认都是从数组中间位置取值作为节点元素,一般不会随机取,所以想构成不平衡的二叉树是自找麻烦。
在二叉树:构造二叉树登场!(opens new window)和二叉树:构造一棵最大的二叉树(opens new window)中其实已经讲过了,如果根据数组构造一棵二叉树。
本质就是寻找分割点,分割点作为当前节点,然后递归左区间和右区间。
那么为问题来了,如果数组长度为偶数,中间节点有两个,取哪一个?
取哪一个都可以,只不过构成了不同的平衡二叉搜索树。
C++完整代码如下:
/*** 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:TreeNode* traversal(vector<int>& nums, int left, int right){if(left > right){ // 如果区间元素与足以构成节点,即区间为空return nullptr;}int middle = left + ((right - left) >> 1); // BST对应数组的中间节点就是根节点TreeNode* node = new TreeNode(nums[middle]); // 构建根节点node->left = traversal(nums, left, middle - 1); // 递归左子树node->right = traversal(nums, middle + 1, right); // 递归右子树return node;}TreeNode* sortedArrayToBST(vector<int>& nums) {return traversal(nums, 0, nums.size() - 1);}};
理解递归我觉得就可以了,迭代法的话,面试应该不会这么变态同时让写递归和迭代。
Java代码:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/class Solution {public TreeNode buildBST(int[] nums, int left, int right){if(left > right) return null; // 如果left>right,说明当前区间为nullint middle = left + ((right - left) >> 1);TreeNode node = new TreeNode(nums[middle]); // new一个节点node.left = buildBST(nums, left, middle - 1); // 递归左子树node.right = buildBST(nums, middle + 1, right); // 递归右子树return node;}public TreeNode sortedArrayToBST(int[] nums) {return buildBST(nums, 0, nums.length - 1);}}
6、从中序与后续遍历构建二叉树
106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

下面的代码,我不做解释,如果看不懂,请看这里 二刷代码随想录 - 二叉树 - 从中序与后序遍历构建二叉树
2、将二叉搜索树变平衡
1382. 将二叉搜索树变平衡 - 力扣(LeetCode)







