Leetcode114
解题的关键是:左子树的最下最右的节点,是右子树的父节点.
为什么一个先序遍历,我用后序?
- 回溯算法!!
- 从右到左的进行排序!
- last真的只记录这个顺序的上一个
- 因为left==nullptr,必定会有丢失!
TreeNode* last = nullptr;
void flatten(TreeNode* root) {
if (root == nullptr) return;
flatten(root->right);
flatten(root->left);
root->right = last;
root->left = nullptr;
last = root;
}
430.
class Solution {
private Node ans;
private Node cur;
public Node flatten(Node head) {
if(head == null){
return null;
}
dfs(head);
return ans;
}
//看成二叉树的前序遍历
private void dfs(Node node){
if(node==null){
return;
}
//相当于前序遍历的主体,把遍历到的当前节点放入新的链表里
if(cur==null){
ans = new Node();
ans.val = node.val;
cur = ans;
}else{
Node newNode = new Node();
newNode.val = node.val;
cur.next = newNode;
newNode.prev = cur;
cur = newNode;
}
//优先迭代子节点,再迭代下一个节点
dfs(node.child);
dfs(node.next);
}
}
- 不要被有无null给欺骗了??
- 每一次都新建一个node
- 这个node后面接,前面接什么都要
- cur保存断的那个!
- child在前,那个next在后
class Solution {
public:
Node* ans;
Node* cur;
Node* flatten(Node* head) {
if(head==NULL) return head;
dfs(head);
return ans;
}
void dfs(Node* node){
if(node==NULL) return;
if(ans==NULL){
ans = new Node;
ans->val = node->val;
cur = ans;
}else{
Node* tmp = new Node;
tmp->val = node->val;
tmp->prev = cur;
cur->next = tmp;
cur = tmp;
}
dfs(node->child);
dfs(node->next);
}
};
124.
- 不解为何最后return的那个,如果比0小,是相当于这条支路不作选择嘛?
class Solution {
int result = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
dfs(root);
return result;
}
// 函数功能:返回当前节点能为父亲提供的贡献,需要结合上面的图来看!
private int dfs(TreeNode root) {
// 如果当前节点为叶子节点,那么对父亲贡献为 0
if(root == null) return 0;
// 如果不是叶子节点,计算当前节点的左右孩子对自身的贡献left和right
int left = dfs(root.left);
int right = dfs(root.right);
// 更新最大值,就是当前节点的val 加上左右节点的贡献。
result = Math.max(result, root.val + left + right);
// 计算当前节点能为父亲提供的最大贡献,必须是把 val 加上!
int max = Math.max(root.val + left, root.val + right);
// 如果贡献小于0的话,直接返回0即可!
return max < 0 ? 0 : max;
}
}
//我的
class Solution {
public:
int res = INT_MIN;
int maxPathSum(TreeNode* root) {
dfs(root);
return res;
}
int dfs(TreeNode* root){
if(root==nullptr) return 0;
int left = dfs(root->left);
int right = dfs(root->right);
int mmax = max(left+ root->val , right+root->val);
res = max(res, left+right+root->val);
return mmax>0? mmax:0;
}
};
112.
该种解法总有不到十个通过不了??
class Solution {
public:
bool res = false;
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==nullptr) return false;
dfs(root, targetSum, 0);
return res;
}
void dfs(TreeNode* root,int targetSum, int sum){
if(root==nullptr){
if(sum==targetSum) res= true;
return;
}
dfs(root->left, targetSum, sum+root->val);
dfs(root->right, targetSum, sum+root->val);
}
};
- 可以用-法,不必一直加一个!
- return的是||, 就可以左边右边任意一个是true,就会被传送出来为true!
-
&& targetSum-root->val==0
class Solution {
public boolean hasPathSum(TreeNode root, int sum) {
if (root == null) {
return false;
}
if (root.left == null && root.right == null) {
return sum - root.val == 0;
}
return hasPathSum(root.left, sum - root.val)
|| hasPathSum(root.right, sum - root.val);
}
}
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==nullptr) return false;
if(root->left==nullptr && root->right==nullptr && targetSum-root->val==0) return true;
return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum-root->val);
}
};
113.
这种办法要重复两次的计算!!!什么时候跳出循环,会多进入一层的循环,于是答案左右两个,会重了翻倍
class Solution {
public:
vector<vector<int>> ans;
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
dfs(root, targetSum, {});
return ans;
}
void dfs(TreeNode* root, int targetSum, vector<int> path){
if(root == nullptr){
if(targetSum==0) ans.push_back(path);
return;
}
path.push_back(root->val);
targetSum = targetSum-root->val;
dfs(root->left, targetSum, path);
dfs(root->right, targetSum, path);
}
};
//为何出错??
class Solution {
public:
vector<vector<int>> ans;
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
dfs(root, targetSum, {});
return ans;
}
void dfs(TreeNode* root, int targetSum, vector<int> path){
if(root == nullptr){
return;
}
path.push_back(root->val);
targetSum = targetSum-root->val;
if(root->left==nullptr && root->right==nullptr && targetSum==0){
ans.push_back(path);
}
dfs(root->left, targetSum, path);
dfs(root->right, targetSum, path);
}
};
437.双重递归
不要以为是递归就不是顺序执行了!!
- 出发的头节点摇摆不定,第一重递归就是头节点的确定
- 第二重递归是左右出发去找合适的支流,一找到就退出!
class Solution {
public:
int ans;
int pathSum(TreeNode* root, int targetSum) {
if(root==nullptr) return 0;
dfs(root, targetSum);
pathSum(root->left, targetSum);
pathSum(root->right, targetSum);
return ans;
}
void dfs(TreeNode* root, int targetSum){
if(root==nullptr) return;
targetSum -= root->val;
if(targetSum==0) ans++;
dfs(root->left, targetSum);
dfs(root->right, targetSum);
}
};
687.
int longestUnivaluePath(TreeNode *root)
{
if (!root)
return 0;
longestPath(root);
return res;
}
int longestPath(TreeNode *root)
{
if (!root)
return 0;
int left = longestPath(root->left), right = longestPath(root->right);
// 如果存在左子节点和根节点同值,更新左最长路径;否则左最长路径为0
if (root->left && root->val == root->left->val)
left++;
else
left = 0;
if (root->right && root->val == root->right->val)
right++;
else
right = 0;
res = max(res, left + right);
return max(left, right);
}
class Solution {
public:
int res;
int longestUnivaluePath(TreeNode* root) {
backtracking(root);
return res;
}
int backtracking(TreeNode* root){
if(root==nullptr) return 0;
int left = backtracking(root->left);
int right = backtracking(root->right);
if(root->left && root->left->val == root->val){
left++;
}else{
left = 0;
}
if(root->right && root->right->val == root->val){
right++;
}else{
right =0;
}
res = max(res, left+right);
return max(left, right); //毕竟一次只能是走一边的,不可能同时两边都走, 故一个根节点只能对应其中之一
}
};
988
- 按照字典序的排序就可以!sort解决
vector<string> path;
string smallestFromLeaf(TreeNode *root)
{
dfs(root, "");
sort(path.begin(), path.end()); //升序排序
return path[0];
}
void dfs(TreeNode *root, string s)
{
if (!root)
return;
s += 'a' + root->val;
if (!root->left && !root->right)
{
reverse(s.begin(), s.end()); //题目要求从根节点到叶节点,因此反转
path.push_back(s);
return;
}
dfs(root->left, s);
dfs(root->right, s);
}
//我的,计算极其慢!
class Solution {
public:
vector<string> path;
string smallestFromLeaf(TreeNode* root) {
dfs(root, "");
sort(path.begin(), path.end());
return path[0];
}
void dfs(TreeNode* root, string s){
if(root==NULL){
return;
}
s += root->val + 'a';
if(root->left==NULL && root->right==NULL){
reverse(s.begin(), s.end());
path.push_back(s);
return;
}
dfs(root->left, s);
dfs(root->right, s);
}
};