周记-深度优先

在看过深度搜索和广度搜索之后,就想着从Leetcode上找一些题刷一下,

本来以为可以日刷五十道题,最后成了每天刷五道,这里进行周总结。

我的代码好多都是看别人的,先理论学习

1   124.二叉树的最大路径和

传送门:https://leetcode-cn.com/problems/binary-tree-maximum-path-sum/

//这个题的意思是返回一个最大路径的和,不是返回子树的和。

   -10
   / \
  9  20
    /  \
   15   7

用这个图来解释一下,这个图中最大路径和是42,很容易算到,但是当树变为如下形式的时候

 

   10
   / \
  9  20
    /  \
   15   7

最大和为54,是因为一条路径不可能同时经过一个节点的左子树和右子树。

//可能是因为我理解的不好,接下来进行代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int maxPathSum(TreeNode* root, int &val)
{
	if (root == nullptr) return 0;
	int left = maxPathSum(root->left, val);
	int right = maxPathSum(root->right, val);
	int lmr = root->val + max(0, left) + max(0, right);
    //lmr记录的就是左右加上根节点的值。
	int ret = root->val + max(0, max(left, right));
	val = max(val, max(lmr, ret));
    //cout<<root->val<<" "<<left<<" "<<right<<" "<<lmr<<" "<<ret<<" "<<val<<endl;
	return ret;
    //为什么需要lmr和ret呢?
    //ret就是看我们第二颗树,当走到根节点的时候,我们需要的是左和右节点的最大值,这里涉及到的只是右节点的一个子树,所以需要有ret去取到这个右节点路径上的最大值。
    //lmr就是记录本节点加上左和右节点的最大值
    //子函数返回的是一个分支的最大值。
    //   最后主函数返回这二者最大值。
}

int maxPathSum(TreeNode* root) 
{
	int val = INT_MIN;
	maxPathSum(root, val);
	return val;
}
    //勉强解释一下,就是这样的,res记录最大值,post返回值记录的是左右子树中的较大值加上本节点的值
    //为什么要这样呢?
    //我的理解出现了问题,我的理解是要返回节点最大值
    //它这里的题意是有一条路径,得到·该路径的最大值。
};

 2   110. 平衡二叉树

传送门:https://leetcode-cn.com/problems/balanced-binary-tree/

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1,就很容易理解。

 

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int f=0;
    int dfs(TreeNode* root){
        if(root==NULL) return 0;
        int l=dfs(root->left);
        int r=dfs(root->right);
        if(abs(l-r)>1) f=1;
        return max(l,r)+1; 
//当root时候,l和r记录的是其左右子树的最大高度,所以比较就完事了
    }
    bool isBalanced(TreeNode* root) {
        dfs(root);
        if(f) return false;
        else return true;
    }
};

 3   199.二叉树的右视图

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

传送门:https://leetcode-cn.com/problems/binary-tree-right-side-view/

 输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:

   1            <---
 /   \
2     3         <---
 \     \
  5     4       <---

感觉题目说的也是比较清楚了,开始代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
        vector<int> rightSideView(TreeNode* root) {
            if(!root)
                return {};
            vector<int> ans;
            queue<TreeNode*> que;
            que.push(root);

            while(!que.empty()) {
                int len = que.size();
                for(int i = 0; i< len; i++) {
                    auto q = que.front();
                    que.pop();
                    if(i == len-1) {//这个就是到本层的最后一个元素
                        ans.push_back(q->val);
                    }
                    if(q->left)
                        que.push(q->left);
                    if(q->right)
                        que.push(q->right);
                }
            }
            return ans;
    }

};

 queue这个容器在我最近几天就见过很多次,但我还是不会活用。queue特点是先进先出。

这里给大家解释一下while里面的代码:

在while之前,队列就保存了根值,所以肯定可以进入while,用len保存长度,pop()就是出队列,两个if就是将左右子树入队列

整个for结束后,queue就保存了下一层的所有值。

i == len-1,说明已经到了最后一个元素,这时候就用vector容器保存改值。

 

4   98.验证二叉树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

节点的左子树只包含小于当前节点的数。
节点的右子树只包含大于当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。

///这个就是说要保证左子树的所有节点值小于根节点的值,右节点的所有节点值大于根节点的值

在自己内部也要符合相应条件。

下面开始代码

class Solution {
public:
    bool helper(TreeNode* root, long long low, long long high) {
        if (root == nullptr) return true;
        if (root -> val <= low || root -> val >= high) return false;
        return helper(root -> left, low, root -> val) && helper(root -> right, root -> val, high);
    }
    bool isValidBST(TreeNode* root) {
        return helper(root, LONG_MIN, LONG_MAX);
    }
};

5   99.恢复二叉树

二叉搜索树中的两个节点被错误地交换。

请在不改变其结构的情况下,恢复这棵树。

//额如果二叉树的性质是这样的话,那我前面用到的二叉树是什么?

这个重点就是只有两个节点是颠倒位置的

//同时还要保证上一题的性质不变

所以通过和根值比较,从左子树中找最大值,从右子树中找最小值,如果这是正确的二叉树,说明是找不到这两个值的。

下面开始代码

class Solution {
public:
    TreeNode* mx;
    TreeNode* mn;
    void findmax(TreeNode* node) {
        if(node == nullptr) {
            return;
        }
        if(node->val > mx->val) {
            mx = node;
        }
        findmax(node->left);
        findmax(node->right);
    }
    void findmin(TreeNode* node) {
        if(node == nullptr) {
            return;
        }
        if(node->val < mn->val) {
            mn = node;
        }
        findmin(node->left);
        findmin(node->right);
    }
    void recoverTree(TreeNode* root) {
        if(root == nullptr)
            return;
        mx = root;
        mn = root;
        findmax(root->left);
        findmin(root->right);
        if(mx->val > mn->val) {
            auto tmp = mn->val;
            mn->val = mx->val;
            mx->val = tmp;
            return;
        }
        recoverTree(root->left);
        recoverTree(root->right);
    }
};

也许我的解析只能我自己理解?还行吧

6   100.相同的树

给定两个二叉树,编写一个函数来检验它们是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

就是各个节点一一比较

下面开始代码

class Solution {
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
        if(p == NULL && q == NULL) return true;
        if(p == NULL || q == NULL) return false;
        if(p->val!=q->val)  return false;
        return isSameTree(p->left, q->left)&&isSameTree(p->right, q->right);
    }
};

7   101. 对称二叉树

给定一个二叉树,检查它是否是镜像对称的。

    1
   / \
  2   2
 / \ / \
3  4 4  3

就是根左子树的左节点和根右子树的右节点比较。根左子树的右节点和根右子树的左节点比较。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        return ismirror(root,root);
    }
    bool ismirror(TreeNode* p, TreeNode *q) {
        if(!p&&!q)  ///如果这两个节点均为空的话
            return true;
        if(!p||!q) 
        return false;
        if(p->val == q->val)
            return ismirror(p->left,q->right)&&ismirror(p->right,q->left);
        return false;
    }
};

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值