您的位置:首页 > 职场人生

四道微软面试算法题

2008-10-28 20:56 295 查看
http://topic.csdn.net/u/20081006/16/75461d49-6a8f-4684-84b6-aceee56c832f.html

(1)
一个整数数列,元素取值可能是0~65535中的任意一个数,相同数值不会重复出现。0是例外,可以反复出现。
请设计一个算法,当你从该数列中随意选取5个数值,判断这5个数值是否连续相邻。
注意:
- 5个数值允许是乱序的。比如: 8 7 5 0 6
- 0可以通配任意数值。比如:8 7 5 0 6 中的0可以通配成9或者4
- 0可以多次出现。
- 复杂度如果是O(n2)则不得分。

(2)
设计一个算法,找出二叉树上任意两个结点的最近共同父结点。
复杂度如果是O(n2)则不得分。

(3)
一棵排序二叉树,令 f=(最大值+最小值)/2,设计一个算法,找出距离f值最近、大于f值的结点。
复杂度如果是O(n2)则不得分。

(4)
一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
复杂度最好是O(n),如果是O(n2)则不得分。

自己做了一下,程序如下
(1)

// 返回0表示正确,否则返回失败的索引值
int Check(int* p_data, int p_nCount)
{
int i, end, zeroCount=0;

// 对数据进行从小到大排序
Sort(p_data, p_nCount);
// 检查0的个数
for(i=0; i<p_nCount; i++)
{
if(p_data[i]==0) zeroCount++;
else break;
}

// 从5开始,到非0值的循环
i = p_nCount;
end = zeroCount+1;
while(i-- > end)
{// 如果前后相差大于1,表示不连续
if((p_data[i] - p_data[i-1]) != 1)
{// 看能否用足够的0不上,计算剩余的0个数
zeroCount -= p_data[i] - p_data[i-1]-1;
if(zeroCount < 0) return i;
}
}
return 0;
}

(2)
void swap(Node** a, Node** b)
{
Node * p = *a;
*b = *a;
*a = p;
}
void Check(Node * root, Node* a, Node* b)
{
Node * parent = NULL;
if (a == NULL || b == NULL) printf("NULL/r/n");
printf("a=%d, b=%d, parent=", a->value, b->value);

if (a->GetLevel() < b->GetLevel()) // 检查两个节点深度,如果b比a深,交换a、b,让a的深度比b大

{
swap(&a, &b);
}
while(a->GetLevel() > b->GetLevel()) //对齐深度,这样才好比较
{
a = a->parent;
}
if (a == b) parent = a; //对齐后如果是同一节点,那么共同父节点取a

else
{
while(a->parent != b->parent) //检查a、b的父节点,如果不是,同时提升a、b节点
{
a = a->parent;
b = b->parent;
}
parent = a->parent;//最后得到共同父节点
}
printf("%d/r/n", parent->value);
}

(3)
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "node.h"

int sum = 0; // 比较次数总数
Node * Check(Node * p, int f)
{
sum++;
if (p==NULL) return NULL;

sum++;
if (p->value >= f) // 当前节点大于f时,要检查左节点是否有更接近的值

{
Node* q = Check(p->left,f);
sum++;
return (q!=NULL)?q:p; // 左节点没合适的值时,用当前节点,否则要返回的节点

}
else // 当前节点小于f时,检查右节点是否有更接近的值
{
return Check(p->right,f);
}
}

// 给出根节点,计算最接近 f=(最大值+最小值)/2 的节点
void Check(Node * root)
{
Node * min = root->GetMinNode();
Node * max = root->GetMaxNode();
int f = (max->value + min->value)/2;
printf("min=%d, max=%d, f=%d , ", min->value, max->value, f);
sum=0;
Node* p = Check(root, f);
printf("target=%d/t/t%d/r/n", p->value,sum);
}

// 生成测试数据
Node * CreateTestTree(void)
{
int data[]={100,50,30,20,40,70,60,80,150,130,120,140,170,160,180};
int len = 15;
Node * root= new Node(data[0]);
for(int i = 1; i < len; i++)
{
root->Insert(data[i]);
}
return root;
}

// 主测试函数
void main(void)
{
clrscr();
Node * treeRoot = CreateTestTree();
treeRoot->PrintTree(40,1,3);
Node * p = NULL;
// 单独测试 Node * Check(Node * p, int f)
for (int i=10;i<=200 ;i+=5)
{
p = Check(treeRoot, i);
printf ("f=%d, node=%d/r/n",i,p->value);
}

// 测试题目3
Check(treeRoot);
delete treeRoot;
treeRoot = NULL;
return ;
}

(4)
#include <stdio.h>
// 题目4:
//一个整数数列,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
//复杂度最好是O(n),如果是O(n2)则不得分。

// buf中数据应该已经排序
// 返回匹配数对数量
// 算法中遍历1次数组,复杂度O(N)

int c4(int* buf, int count)
{
const int *p = buf; // 前指针
const int *q = buf+count-1; // 后指针
int n=*q+1; // N值
int c = 0; // 匹配数量
int compare = 0; //比较次数

while (p<q) // 当前指针小于后指针时,循环数组
{ compare++;
if ((*p + *q) == n) // 命中,计数加1,移动指针
{ compare++; printf("%d,%d; ", *p,*q);
c++; p++; q--;
}
else
{
if ((*q + *p ) > n )
q--; // 当前2个值大于N时,前指针的值可能还有匹配,后指针左移
else
p++; // 当前2个值小于N时,后指针的值可能还有匹配,前指针右移
}
}
printf("compare=%d;/r/n ", compare); // 打印总比较次数
return c;
}

void test(int index, const int* buf, int count, int expected)
{

for(int i=0; i<count; i++) printf("%2d,", buf[i]);
int actual = c4(buf, count);
printf("test %2d/t [%s] expected=%d, actual=%d/r/n/r/n",
index, expected==actual?" ok ":"false", expected, actual);
}

int main(void)
{
int i=1;
int t0[10]={1,2,3,4,5,95,96,97,98,99};
int t0_expected=5;
test(i++, t0, 10, t0_expected);

int t1[10]={1,2,13,14,15,95,96,97,98,99};
int t1_expected=2;
test(i++, t1, 10, t1_expected);

int t2[10]={1,2,3,44,55,95,96,97,98,99};
int t2_expected=3;
test(i++, t2, 10, t2_expected);

int t3[10]={1,12,13,87,88,95,96,97,98,99};
int t3_expected=3;
test(i++, t3, 10, t3_expected);

int t4[10]={1,20,30,40,50,51,96,97,98,99};
int t4_expected=1;
test(i++, t4, 10, t4_expected);

int t5[16]={1,12,13,14,20,30,31,32,33,70,80,95,96,97,98,99};
int t5_expected=3;
test(i++, t5, 16, t5_expected);


int t6[16]={1,3,4,12,13,14,20,30,31,70,80,85,86,87,88,99};
int t6_expected=6;
test(i++, t6, 16, t6_expected);

return 0;
}
用到的Node类
// Node.h
#include <stdio.h>

#ifndef NODE
#define NODE

class Node
{
public :
int value;
Node* parent;
Node* left;
Node* right;

private:
int level;
// 打印树时的间隔比例因子
static const int SPACE;
int m_nMaxRow;
public :

Node(void);
Node(int p_value);
Node(Node * p_parent);
Node(int p_value, Node * p_parent);

// 删除树
~Node();

// 打印树
void PrintTree();
// 打印树 x = col, y = row,不是很好看 :P
void PrintTree(int x, int y, int z);
// 获取树深度
int GetLevel();
// 找最小值节点
Node* GetMinNode();
// 找最大值节点
Node* GetMaxNode();
// 插入新数据
Node* Insert(int p_value);
};

#endif
// Node.cpp

#include <stdio.h>
#include <conio.h>
#include "node.h"

//using namespace std;

const int Node::SPACE = 3;

Node::Node(void)
{
m_nMaxRow = 0;
parent = NULL;
left = NULL;
right = NULL;
level = -1;
}

Node::Node(int p_value)
{
m_nMaxRow = 0;
value = p_value;
parent = NULL;
left = NULL;
right = NULL;
level = -1;
}
Node::Node(Node * p_parent)
{
m_nMaxRow = 0;
parent = p_parent;
left = NULL;
right = NULL;
if(p_parent) level = p_parent->level+1;
}
Node::Node(int p_value, Node * p_parent)
{
m_nMaxRow = 0;
value = p_value;
parent = p_parent;
left = NULL;
right = NULL;
if(p_parent) level = p_parent->level+1;
}

// 删除树
Node::~Node()
{
if (this->left) {delete left; left = NULL;}
if (this->right) {delete right; right = NULL;}
}

// 打印树
void Node::PrintTree()
{
if (this->left) this->left->PrintTree();
printf("%d ",this->value);
if (this->right) this->right->PrintTree();
}
// 打印树
// x = col, y = row
void Node::PrintTree(int x, int y, int z)
{
if (x<0) x = 0;
if (y>25) return;
// if (y>m_nMaxRow) m_nMaxRow = y;
if (this->left) this->left->PrintTree(x-SPACE-z-z, y+1, z-1);

gotoxy(x, y);
printf("%d ",this->value);
if (this->right) this->right->PrintTree(x+SPACE+z+z, y+1, z-1);
}
// 获取树深度
int Node::GetLevel()
{
// 如果已经初始化,直接返回
if (level != -1)
return level;

// 否则算计深度
level = 0;
Node * p = this->parent;
while(p != NULL)
{
level ++;
p = p->parent;
}
return level;
}
// 找最小值节点
Node* Node::GetMinNode()
{
if (this->left != NULL) return this->left;
else return this;
}
// 找最大值节点
Node* Node::GetMaxNode()
{
if (this->right != NULL) return this->right;
else return this;
}

// 插入新数据
Node* Node::Insert(int p_value)
{
if (p_value > this->value)
{
if(this->right) return this->right->Insert(p_value);
else return this->right = new Node(p_value, this);
}
else
{
if(this->left) return this->left->Insert(p_value);
else return this->left = new Node(p_value, this);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: