【面试题】树的高度

题目来自:陈利人老师的微博和微信!

给定数组A,大小为n,数组元素为1到n的数字,不过有的数字出现了多次,有的数字没有出现。请给出算法和程序,统计哪些数字没有出现,哪些数字出现了多少次。能够在O(n)的时间复杂度,O(1)的空间复杂度要求下完成么?

思路:

如果现在我们有一个树的表示如下

[-1,0,0,1,0,2,1,4,2,7,6,7,10]

可见树的根为0.而1的父亲结点为0,而0为根结点。更多:3的父亲结点是1,而1的父亲结点是0,而0是根节点。所以我们可以得到下面的代码:

#include <iostream>
#include <stdlib.h>

using namespace std;

int main(int argc, char *argv[])
{
  int father[13] = {-1,0,0,1,0,2,1,4,2,7,6,7,10};
  int len[13] = {0};
  for(int i = 0; i < 13; i++){
      int j = i;
      while(father[j] != -1){
        j = father[j];
        len[i] ++;
      }
  }
  for(int i = 0; i < 13; i++)
     cout << len[i] << " ";
  cout << endl;
  system("PAUSE");	
  return 0;
}
得到的结果是:0 1 1 2 1 2 2 2 2 3 3 3 4

则进行一次排序可以得到结果。

反思路:如果某一数在原father数组没有出现,则该数所对应的结点为叶子结点,反过来求也是可以的。

那么是否能够继续改进呢?通过上面的计算过程,我们可以发现,在计算4->2->3->-1的时候,显然2->3->-1已经计算过了,不需要再浪费时间重新计算一遍。示例代码如下:

#include <iostream>
#include <stdlib.h>

using namespace std;

int father[13] = {-1,0,0,1,0,2,1,4,2,7,6,7,10};
int len[13] = {0};

int curlen(int i){
   if(father[i] == -1)
   return 0;
   else{
      if(len[father[i]] != 0)
        return len[father[i]] + 1;
      else
        return curlen(father[i]) + 1; 
   }
}
int main(int argc, char *argv[])
{
  for(int i = 0; i < 13; i++){
    len[i] = curlen(i);
  }
  for(int i = 0; i < 13; i++){
    cout << len[i] << " ";
  }
  cout << endl;
  system("PAUSE");	
  return 0;
}
陈老师的代码:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值