数据结构——树(03二叉树,与路径有关的问题,代码练习)
文章目录
- 五、二叉树的路径
- 5.1左叶子之和
- 5.2根节点到叶子节点,二叉树的路径
- 5.3十进制二叉树 的路径之和
- 5.3二进制二叉树 的路径之和
- 5.4二叉树里的路径
五、二叉树的路径
序号 | 题目 | 链接 |
---|---|---|
1 | 左叶子之和 | https://leetcode.cn/problems/sum-of-left-leaves/description/?envType=problem-list-v2&envId=tree |
2 | 根节点到叶子结点,二叉树的所有路径 | https://leetcode.cn/problems/binary-tree-paths/description/?envType=problem-list-v2&envId=tree |
3 | 根节点到叶子结点,二叉树的所有路径总和 | https://leetcode.cn/problems/path-sum/description/?envType=problem-list-v2&envId=tree |
4 | 根节点到叶子结点,路径之和为target的路径 | https://leetcode.cn/problems/path-sum-ii/description/?envType=problem-list-v2&envId=tree |
5 | 二叉树里,路径之和为target的路径 | https://leetcode.cn/problems/path-sum-ii/description/?envType=problem-list-v2&envId=tree |
1 | 路径之和 | https://leetcode.cn/problems/sum-root-to-leaf-numbers/description/?envType=problem-list-v2&envId=tree |
6 | 路径的二进制之和 | https://leetcode.cn/problems/sum-of-root-to-leaf-binary-numbers/description/?envType=problem-list-v2&envId=tree |
7 | 最长同值路径 | https://leetcode.cn/problems/longest-univalue-path/description/?envType=problem-list-v2&envId=tree |
1 | 路径和相等的最小代价 | https://leetcode.cn/problems/make-costs-of-paths-equal-in-a-binary-tree/description/?envType=problem-list-v2&envId=tree |
5.1左叶子之和
给定二叉树的根节点 root ,返回所有左叶子之和。
int num=0;
//用栈实现先序遍历
void f(TreeNode* root){if(root==nullptr) return ;stack<TreeNode*> st;st.push(root);while(!st.empty()){TreeNode* p=st.top();st.pop();//result.push_back(p->val);if(p->right!=nullptr) st.push(p->right);//if(p->left!=nullptr) st.push(p->left);if(p->left!=nullptr){if(p->left->left==nullptr && p->left->right==nullptr) num+=p->left->val;else st.push(p->left);} }
}
int sumOfLeftLeaves(TreeNode* root) {f(root);return num;
}
5.2根节点到叶子节点,二叉树的路径
返回所有从根节点到叶子节点的路径。
dfs在访问节点的过程中,完善字符串的格式(空时直接存当前节点值,非空时加"->"连接)。然后递归遍历左右子树,同时构建路径。
- 递归终止条件1:空节点直接返回
- 递归终止条件2:访问到叶节点,路径完整,加入结果集
vector<string> result;
void dfs(TreeNode* root,string path){if(root==nullptr) return ;//访问根节点if(path.empty()) path=path+to_string(root->val);else path=path+"->"+to_string(root->val);//访问到叶子节点结束if(root->left==nullptr && root->right==nullptr){result.push_back(path);return ;}//左右dfs(root->left,path);dfs(root->right,path);
}
vector<string> binaryTreePaths(TreeNode* root) {if(root==nullptr) return {};dfs(root,"");return result;
}
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
bool hasPathSum(TreeNode* root, int targetSum) {dfs(root,0);for(int res:result){if(res==targetSum) return 1;}return 0;
}
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {dfs(root,{});vector<vector<int>> h;for(vector<int> res:result){int sum=0;for(int r:res){sum+=r;}if(sum==targetSum) h.push_back(res);}return h;
}
5.3十进制二叉树 的路径之和
int dfs(TreeNode *root, int val) {if (root == nullptr) return 0;val = val * 10 + root->val;if (root->left == nullptr && root->right == nullptr) return val;return dfs(root->left, val) + dfs(root->right, val);
}
int sumNumbers(TreeNode* root) {return dfs(root,0);
}
5.3二进制二叉树 的路径之和
给出一棵二叉树,其上每个结点的值都是 0 或 1 。每一条从根到叶的路径都代表一个从最高有效位开始的二进制数。
例如,如果路径为 0 -> 1 -> 1 -> 0 -> 1,那么它表示二进制数 01101,也就是 13 。
对树上的每一片叶子,我们都要找出从根到该叶子的路径所表示的数字。
int dfs(TreeNode *root, int val) {if (root == nullptr) return 0;val = (val << 1) | root->val;if (root->left == nullptr && root->right == nullptr) return val;return dfs(root->left, val) + dfs(root->right, val);
}
int sumRootToLeaf(TreeNode* root) {return dfs(root, 0);
}
vector<string> result;
void dfs(TreeNode* root,string path){if(root==nullptr) return ;path += to_string(root->val);if(root->left==nullptr && root->right==nullptr){result.push_back(path);return ;}dfs(root->left,path);dfs(root->right,path);
}
// 将二进制字符串转换为十进制整数
int binaryToDecimal(const string& binary) {int num = 0;for (char c : binary) {// 左移一位相当于乘以2,加上当前位的值(0或1)num = (num << 1) + (c - '0');}return num;
}
int sumRootToLeaf(TreeNode* root) {dfs(root,"");int total = 0;for (const string& res : result) {total += binaryToDecimal(res);}return total;
}
5.4二叉树里的路径
给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。
- 前缀和定义:从根节点到当前节点的路径上,所有节点值的累加和,记为 prefixSum。
- 路径和与前缀和的关系:若从节点 A 到节点 B 的路径和为 targetSum,则 prefixSum(B) - prefixSum(A的父节点) = targetSum(即 prefixSum(A的父节点) = prefixSum(B) - targetSum)。
= 哈希表作用:记录 “前缀和出现的次数”,遍历到当前节点时,直接查询 prefixSum - targetSum 出现的次数,即为以当前节点为终点的有效路径数。
int dfs(TreeNode* node, long long currentPrefix, int target, unordered_map<long long, int>& prefixCount) {if (node == nullptr) return 0;currentPrefix += node->val;// 计算当前有效路径数int res = prefixCount[currentPrefix - target];// 更新前缀和计数prefixCount[currentPrefix]++;// 递归左右子树res += dfs(node->left, currentPrefix, target, prefixCount);res += dfs(node->right, currentPrefix, target, prefixCount);// 回溯prefixCount[currentPrefix]--;return res;
}
int pathSum(TreeNode* root, int targetSum) {unordered_map<long long, int> prefixCount;prefixCount[0] = 1; // 初始化前缀和为0的情况return dfs(root, 0, targetSum, prefixCount);
}