程序员面试经典chapter4 Trees and Graphs

第一题 二叉树平衡检查

题目描述: 检查二叉树是否平衡,对于任意一个节点来说两个子树的高度差小于1
题目给出的函数为

class Balance {
public:
    bool isBalance(TreeNode* root) {
        // write code here
    }
};

遍历方式应该用后序(post-order)先左边再右边最后到根,所以当判断根节点是否平衡的时候就判断下一个depth节点是否平衡,以此类推。用递归的的方式来判断平衡,不要多次计算子节点,子树的高度。主要函数以递归的形式求深一层的节点平衡,一个utility函数用来返回求得的当前节点的深度,所以最后通过代码为:


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

class Balance {
public:
    bool isBalance(TreeNode* root) {
        if(root == NULL)
            return true;
        // write code here
        if((depth(root->left)-depth(root->right)>1) || (depth(root->left)-depth(root->right)<-1))
           return false;
        else
            return isBalance(root->left)&&isBalance(root->right);
    }
     
    int depth(TreeNode* root){
        if(root == NULL)
            return 0;
        return depth(root->left)>depth(root->right)? depth(root->left)+1:depth(root->right)+1;
    }
};

第二题 有向路径检查

题目描述:检查一个有向图中两个节点之间是否有 有向路径
题目给出的结构体为:

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

单纯的想象,肯定还是遍历了,至于说是深度优先还是广度优先,我一开始也不知道,凭直觉来做,很简单。

从节点a指向节点b(a->b),建立一个循环知会每一个a的neighbour,首先判断a的neighbour是否是b。


queue<UndirectedGraphNode*> que;
        map<UndirectedGraphNode*,bool> map1;
        //que.push(a);
        while(!que.empty()){
            //UndirectedGraphNode* ptr=que.front();
            map1[ptr]=true;
            for(int i=0;i<ptr->neighbors.size();i++)
            {
                if((ptr->neighbors)[i]==b){...}
            }

如果隔壁邻居正好是b,你猜怎样,那就是有向咯,那如果不是,就要从隔壁邻居的隔壁邻居开始找,所以我需要一个可以先进先出的结构,队列。
也就是说在循环a的隔壁邻居之后(a->neighbour),再从刚才的第一个隔壁邻居开始继续寻找a隔壁的隔壁的邻居...以此类推。


while(!que.empty()){
           UndirectedGraphNode* ptr=que.front();
            map1[ptr]=true;
            for(int i=0;i<ptr->neighbors.size();i++)
            {
                if((ptr->neighbors)[i]==b)
                    return true;
                if(ptr->neighbors[i]&&map1[ptr->neighbors[i]]!=true)
                    que.push((ptr->neighbors)[i]);
            }
            que.pop();
        }

回到最开始的问题,这就应该是广度优先遍历了图,因为并没有从单个的neighbour开始立即寻找该neighbour的下一个节点,而是在建立的循环中每次首先遍历周围所有的neighbour。
下面是完整代码:


/*
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
        return check(a,b)||check(b,a);
    }
    bool check(UndirectedGraphNode* a, UndirectedGraphNode* b){
        if(a==NULL||b==NULL)
            return false;
        if(a==b)
            return true;
        queue<UndirectedGraphNode*> que;
        map<UndirectedGraphNode*,bool> map1;
        que.push(a);
        while(!que.empty()){
           UndirectedGraphNode* ptr=que.front();
            map1[ptr]=true;
            for(int i=0;i<ptr->neighbors.size();i++)
            {
                if((ptr->neighbors)[i]==b)
                    return true;
                if(ptr->neighbors[i]&&map1[ptr->neighbors[i]]!=true)
                    que.push((ptr->neighbors)[i]);
            }
            que.pop();
        }
        return false;
    }
};

第三题 实现一个最小BST

题目描述:给定一个array,其中元素按照大小排列,创建一个高度最小的二叉查找树。
首先回顾一下什么是BST好了:

  • 非子叶节点都只有两个子节点,分别是左儿子和右儿子
  • 而每个非子叶节点的左儿子小于该非子叶节点,该非子叶节点又比右儿子小

因为已经既定了一个从小到大排列的数组,那就从中间开始作为该二叉树的根节点,每次insert左儿子(←)和右儿子(→)的时候就正好将前半段与后半段相应的继续递归添加。
其实...好像并没有最小这一说,总之通过代码很简单,在这里:


class MinimalBST {
public:
    int buildMinimalBST(vector<int> vals) {
        // write code here
        int height=0;
        addToTree(vals, 0, vals.size() - 1, height);
        return height;
    }
    TreeNode *addToTree(vector<int> vals,int start,int end,int& n){
        if(end<start){
            n=0;
            return NULL;
        }
        int mid = start + (end - start) / 2;
        TreeNode *midroot = new TreeNode(vals[mid]);//根节点
        int left, right;//左右子树
        midroot->left = addToTree(vals, start, mid - 1, left);//左子树
        midroot->right = addToTree(vals, mid + 1, end, right);//右子树
        n = (left >= right ? left : right) + 1;//计算当前高度
        return midroot;
    }
};

第四题 检查是否为BST

题目描述:实现一个函数检查一个给定二叉树是否为查找二叉树
题目给定结构体:


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

好吧,重复了刚才回顾的BST的定义,就一个非子叶节点来说满足两条:1. 左儿子和右儿子;2.左儿子比该节点小,右儿子比该节点大

root->left->val < root->val
root->right->val > root->val

所以最终通过代码为:


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

class Checker {
public:
    bool checkBST(TreeNode* root) {
        // write code here
        if(root==NULL)
            return true;
         
        if(root->left!=NULL){
            if(root->left->val>root->val)
                return false;
            if(root->left->right!=NULL&&root->left->right->val>root->val)
                return false;
        }
         
        if(root->right!=NULL&&root->right->val<root->val)
            return false;
             
        return checkBST(root->left) && checkBST(root->right);
    }
};

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,192评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,186评论 1 303
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 110,844评论 0 252
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,471评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,876评论 3 294
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,891评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,068评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,791评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,539评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,772评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,250评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,577评论 3 260
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,244评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,146评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,949评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,995评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,812评论 2 276

推荐阅读更多精彩内容

  • 树的概述 树是一种非常常用的数据结构,树与前面介绍的线性表,栈,队列等线性结构不同,树是一种非线性结构 1.树的定...
    Jack921阅读 4,375评论 1 31
  • 红黑树(英语:Red–black tree)是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途...
    卡巴拉的树阅读 15,080评论 11 113
  • 去年二叉树算法的事情闹的沸沸扬扬,起因是Homebrew 的作者 @Max Howell 在 twitter 上发...
    Masazumi柒阅读 1,530评论 0 8
  • 二叉树-你必须要懂!(二叉树相关算法实现-iOS) http://www.cnblogs.com/manji/p/...
    汉秋阅读 1,823评论 0 16
  • 在这里,希望喜欢它的人一起每日感悟人生哲理,为你的生活多一点改变。 1、夜,有它特别的气息,寂静,有它自己的声音。...
    林窗鲸落阅读 277评论 0 0