• 检查一个二叉树是否平衡的算法分析与C++实现


    今天面试一个实习生,就想既然是未出校园,那就出一个比较基础的题吧,没想到答的并不如人意,对于树的操作完全不熟悉,因此此题算是未作答。原来我想看一下他分析问题的思路,优化代码的能力。接下来会把最近半年我出的面试题整理出来,以来share给其它同事,而来算是自己校园记忆的一个总结,毕竟自己在项目中已经很久未用到这些知识。其实很多题目都是来源于CareerCup.com。这上面汇集了许多IT名企的面试笔试题目,非常值得找工作的人学习。

    言归正传,什么是二叉树是否平衡的定义,如果面试者不知道,那肯定要提出来,而不是简简单单说我对树不熟悉,或者找其他更多更多的理由。

    其实可以根据平衡的定义,直接递归访问整棵树,计算子树的高度。

    struct TreeNode{
    	TreeNode *leftChild;
    	TreeNode *rightChild;
    	int data;
    };
    
    int getHeight(const TreeNode* root){
    	if( root == nullptr){
    		return 0;
    	}
    	
    	return max(getHeight(root->leftChild), getHeight(root->rightChild)) + 1;
    }
    
    bool isBalanced(const TreeNode* root){
    	if( root == nullptr){
    		return true;
    	}
    	
    	int heightDiff = abs(getHeight(root->leftChild) - getHeight(root->rightChild));
    	if( heightDiff > 1){
    		return false;
    	}
    	else{
    		return isBalanced(root->leftChild) && isBalanced(root->rightChild);
    	}
    }
    如果开始能给出这个解法那是可以接受的。但是,由于同一个node的高度会被重复计算,因此效率不高。算法复杂度是O(n*logn)。接下来,我们要改进这个算法,使得子树的高度不再重复计算:我们通过删减重复的getHeight(const TreeNode*)调用。其实getHeight不单可以计算子树的高度,其实还可以判断子树是否的平衡的,如果不平衡怎么办?直接返回-1。那该递归调用就可以结束了。

    因此,改进的算法就是从root开始递归检查每个子树的高度,如果子树是平衡的,那么就返回子树的高度,否则返回-1:递归结束,树是不平衡的。

    int checkHeight(const TreeNode* root){
    	if( root == nullptr){
    		return 0;
    	}
    	// check the left subtree is balanced or not.
    	int leftHeight = checkHeight(root->leftChild);
    	if( leftHeight == -1 ){
    		return -1;
    	}
    	
    	// check the right subtree is balanced or not.
    	int rightHeight = checkHeight(root->rightChild);
    	if( rightHeight == -1){
    		return -1;
    	}
    	
    	// check the current tree is balanced or not.
    	int diff = leftHeight - rightHeight;
    	if( abs(diff) > 1){
    		return -1;
    	}
    	else{
    		// return the tree height.
    		return max(leftHeight, rightHeight) + 1;
    	}
    }
    bool isBalanced(const TreeNode* root){
        return ( checkHeight(root) == -1 )? false:true;
    }
    

    由于每个node只会访问一次,因此算法时间复杂度为O(n)。但是需要额外的O(logn)的空间。

  • 相关阅读:
    WCF Restful调用跨域解决方案
    [Asp.net]常见word,excel,ppt,pdf在线预览方案,有图有真相,总有一款适合你!
    人体呼吸信号的数据挖掘
    Spark编译及spark开发环境搭建
    诗两首------重庆项目出差有感
    eclipse安装和中文汉化,以及配置
    Querying CRM data with LINQ
    oracle pl/sql之在java中怎么调用oracle函数
    oracle pl/sql之oracle函数
    oracle pl/sql之java中调用oracle有参存储过程
  • 原文地址:https://www.cnblogs.com/anzhsoft/p/3602982.html
Copyright © 2020-2023  润新知