微软4道面试题

题目:

(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最大值-非0最小值 <=数组长度-1

(2)求两节点的全路径,然后求公共路径

(3)

    a、找到最大值a,找到最小值b 求f  O(log(n))+ O(log(n))+ O(1)= O(log(n))
    b、找所求节点:O(log(n))
    找法:
      当f > node->data 则比较f和node->right 
      当f <= node->data 则比较f和node->left
      利用三个存储量,分别记录前一次比较的符号SymbolLast,本次比较的符号SymbolThis,及可能节点ansNode
      当SymbolLast = " <" 且 SymbolThis = ">" 时,记录前一次值即ansNode= node->parent;

      结论:当比较过程中node->right = null时,结果为ansNode, 当node->left = null时 结果为node

(4)用哈希.
建一个大小为(N+1)/2的哈希表,哈希表初始化为0.
遍历数组:
(1).当arr[i] <=(N+1)/2时,将哈希表中第i位置1.
(2).当arr[i]>(N+1)/2时,将arr[i]散列到第(N+1-i)位,如果哈希表中此位为1,则打印i与N+1-i,并将哈希表此位值置0.
复杂度O(n).

 

 

代码:

 

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

用C描述的算法
功能 :判断随意取的数值是否连续相邻,相邻返回1,否则返回0
参数array :存储随意取的数
参数size :随意取的数的个数
***************************************************************************
*/
int is_progression(array, size)
{
/*最大值的索引和最小值的索引*/
maxIndex
= 0;
minIndex
= 0;

i
= 0;
/*试图找到第一个不为0的元素,初始化maxIndex和minIndex*/
for ( ; i < size; ++i )
{
if ( array[i] != 0 )
{
maxIndex
= minIndex = i;
break;
}
}

/*试图确定随意取的数中的最大值和最小值*/
for ( ; i < size; ++i )
{
if ( array[i] > array[maxIndex] )
{
maxIndex
= i;
}
else if ( array[i] < array[minIndex] )
{
minIndex
= i;
}
}

/*如果最大值和最小值的差小于总个数,则可以判定它们是连续相邻的*/
return (array[maxIndex] - array[minIndex]) < size ? 1 : 0;
}


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

用C描述的算法,注释略
***************************************************************************
*/
typedef
int datatype
typedef
struct tree_node{
datatype data;
struct tree_node *lchild;
struct teee_node *rchild;
}treenode,
*lptreenode;
treenode
* find_parentnode(tree, node1, node2)
{
initstack(s);
push(s, tree);
finded
= 0;
parentnode
= tree;

while ( !stackempty(s) )
{
while ( gettop(s, p) && p )
{
if ( p == node1 )
{
finded
+= 1;
}
if ( p == node2 )
{
finded
+= 1;
}

if ( finded == 0 )
{
parentnode
= p;
break;
}
else if ( finded == 2 )
{
break;
}

push(s, p
->lchild);
}

if ( finded == 3 )
{
break;
}
else if ( parentnode != NULL )
{
while ( pop(s, p) && p == parentnode )
{
break;
}

push(s, p
->rchild);
}
}

return finded == 3 ? parentnode : NULL;
}


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

用C描述的算法,注释略
***************************************************************************
*/
treenode
* find_parentnode(tree, f)
{
tempnode
= tree;
while ( tempnode )
{
if ( tempnode->data > f )
{
if ( NULL == tree->lchild
|| tree->lchild->data <= f )
{
break;
}

tempnode
= tree->lchild;
}
else
{
if ( NULL == (tempnode = tempnode->right)
|| tempnode->data > f )
{
break;
}
}
}

return tempnode;
}


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

用C描述的算法,注释略
***************************************************************************
*/
int get_numberpair_count(array, size, N)
{
count
= 0;
temp_array_size
= N / 2 + 1;
temp_index
= 0;

temp_array[temp_array_size];

for ( i = 0; i < size; ++i )
{
temp_index
= array[i] < temp_array_size ? array[i] : (N-array[i]);
if ( temp_array[temp_index] == 1 )
{
++count;
}
else
{
temp_array[temp_index]
= 1;
}
}

return count;
}

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值