Cracking the Coding Interview: Trees and Graphs

本文深入探讨了二叉树相关的算法问题,包括验证二叉查找树、寻找结点后继、计算路径总和等,并提供了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Validate BST

判断一个二叉树是不是二叉查找树。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/

class Checker {
public:
    int lst = 0;
    bool fst = true;
    bool checkBST(TreeNode* root) {
        // write code here
        if(!root) return true;
        bool ltree = checkBST(root->left);
        if(fst) { lst = root->val; fst = false; }
        else { if(lst > root->val) return false; lst = root->val; }
        bool rtree = checkBST(root->right);
        return ltree&&rtree;
    }
};

Successor

这道题目寻找二叉树中指定结点的下一个结点(即中序遍历的后继)。
给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1。

代码实现:在这里我设置了一个类似于状态机的东西,isFind为0的时候,那么就是没有找到节点值为p的节点;为1的时候就是找到了;为2的时候就是找到之后的后继了;然后在找到后继之后比较是否重复。

class Successor {
public:
    int res = -1;
    int isFind = 0; // 1 is found; 2 is replicate
    int findSucc(TreeNode* root, int p) {
        // write code here
        if(!root) return -1;
        int lres = findSucc(root->left, p);
        if(isFind == 1) { res = root->val; isFind = 2; }
        if(root->val == p && !isFind) isFind = 1;
        if(isFind == 2) { if(root->val == res) return -1; }
        int rres = findSucc(root->right, p);

        return res;
    }
};

Route Between Nodes

对于一个有向图,请实现一个算法,找出两点之间是否存在一条路径。

给定图中的两个结点的指针UndirectedGraphNode* a,UndirectedGraphNode* b(请不要在意数据类型,图是有向图),请返回一个bool,代表两点之间是否存在一条路径(a到b或b到a)。

这里需要注意的是需要判断是否有环的存在,因为环的存在使得队列是无穷大,所以需要有些机制判断是否存在环,以及路径可以从a到b,也可以从b到a,这点需要注意一下。别的东西没有什么提示了,就是一个简单的BFS。

/*
struct UndirectedGraphNode {
    int label;
    vector<struct UndirectedGraphNode *> neighbors;
    UndirectedGraphNode(int x) : label(x) {}
};*/

class Path {
public:
    bool checkPath(UndirectedGraphNode* a, UndirectedGraphNode* b) {
        // write code here
        queue<UndirectedGraphNode* > que;
        que.push(a);
        while(!que.empty()) {
            UndirectedGraphNode* tp1 = que.front();
            que.pop();
            if(tp1->label == b->label) return true;
            if(!tp1->label) tp1->label = INT_MIN;
            else tp1->label = -1*tp1->label;
            for(int i = 0, sz = tp1->neighbors.size(); i < sz; i++)
                if(tp1->neighbors[i]->label >= 0)
                    que.push(tp1->neighbors[i]);
        }

        que.push(b);
        while(!que.empty()) {
            UndirectedGraphNode* tp2 = que.front();
            que.pop();
            if(tp2->label == INT_MIN) tp2->label = 0;
            else if(tp2->label < 0) tp2->label = abs(tp2->label);
            if(tp2->label == a->label) return true;
            tp2->label = INT_MAX;
            for(int i = 0, sz = tp2->neighbors.size(); i < sz; i++)
                if(tp2->neighbors[i]->label != INT_MAX)
                    que.push(tp2->neighbors[i]);  
        } 

        return false;
    }
};

List of Depths

这道题目就是给出一个数组,它需要把数组构成二叉树,然后就是计算构成最短二叉树的深度。

class MinimalBST {
public:
    int buildMinimalBST(vector<int> vals) {
        // write code here
        int size = vals.size() + 1;
        int D = ceil(log(size)/log(2));
        return D;
    }
};

First Common Ancestor

有一棵无穷大的满二叉树,其结点按根结点一层一层地从左往右依次编号,根结点编号为1。现在有两个结点a,b。请设计一个算法,求出a和b点的最近公共祖先的编号。

给定两个int a,b。为给定结点的编号。请返回a和b的最近公共祖先的编号。注意这里结点本身也可认为是其祖先。

测试样例:

2,3

返回:1

class LCA {
public:
    int getLCA(int a, int b) {
        // write code here
        while(a != b) {
            if(a > b) a = a >> 1;
            else b = b >> 1;
        }
        return a;
    }
};

Path With Sum

这道题目是使用了DFS来计算,输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

但是这只是其中一个比较简单的版本,想想如果是不规定起始节点和结束节点呢。

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};*/
class Solution {
public:
    void findPath(vector<vector<int> >& res, vector<int> tmp, int tar, int cur, TreeNode* root) {
        if(!root) {
            if(cur == tar) res.push_back(tmp);
            return;
        }
        cur += root->val;
        tmp.push_back(root->val);
        if(root->left || root->right) {
            findPath(res, tmp, tar, cur, root->left);
            findPath(res, tmp, tar, cur, root->right);
        }
        else findPath(res, tmp, tar, cur, root->left);
    }

    vector<vector<int> > FindPath(TreeNode* root,int tar) {
        vector<int> tmp;
        vector<vector<int> > res;
        if(!root) return res;
        int cur = 0;
        findPath(res, tmp, tar, cur, root);
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值