百度笔试题10.2

题目三:

http://topic.csdn.net/u/20071005/22/73AD4AFD-35B8-4864-AB89-DF45CECED7D6.html

 

 简述:n个空间,存放aa+n-1的数,位置随机且数字不重,a为正且未知.

    现在第一个空间的数被误设置为-1.

 

说明:已经知道被修改的数不是最小的.

 

例子:n=6, a=2,原始的串为5, 3, 7, 6, 2, 4.现在被别人修改为-1, 3, 7, 6, 2, 4.

    现在希望找到5.

 

限制:n不超过1M,现在希望找出这个数,并且实现尽量快.

 

要求:完成函数(实现尽可能高效)

    unsigned int find_lost(const int* source, const length)

    source为数组起址,length为长度.

 

给出思路(文字描述),完成代码,并且分析你算法的时间复杂度.

 

Answer1:(排序太耗时间)

抛砖引玉!!!首先排序,然后从第二个元素开始遍历。第i个元素值=i+1个元素值-1,不满足这个条件,即:得到被修改的值为: i各元素值+1。时间复杂度为o(n)。那么因为要排序,所以时间为O(nlogn)

 

Answer2

思路:

此题关键是hash函数H(X)的设计,为了减少数组遍历次数,可把数组看成环形,

H(X):

H(a[1])=1,

H(x)=(x-a[1]+1+n)%n x <>a[1]

代码如下,复杂度为遍历2次:

 

#include <iostream.h>

#include <string.h>

#include <stdlib.h>

 

#define H(x,a1,n) (x-a1+1+n)%n

 

unsigned int find_lost(const int* source, const length) {

  int h;

  int i;

int ret=-1;

int *a=(int *)malloc(length*sizeof(int));

for(i=0;i <length;i++)

a[i]=0; // 存放hash

a[1]=*(source+1); // 存放hash

// H(x)=(x-a[1]+1+n)%n x <>a[1]

for(i=2;i <length;i++) {

  h=H(*(source+i),*(source+1),length);

  a[h]=*(source+i);

}

for(i=0;i <length;i++) {

if (a[i]==0)

break;

}

free(a);

return a[(i-1+length)%length]+1;

}

 

void main() {

  int a[]={-1, 33, 32, 35, 31, 34};

  cout < <find_lost(a,6) < <endl;

system("PAUSE");

}

 

 

 

 

Answer3

由题目可知数组里的数字是连续不重复的,所以前N项和很容易求得。

遍历整个数组(从第二个开始,-1不算),求出数组的和total,顺便求出最小值min。结果就是(min+min+length-1)*length/2-total.N项和减去前N-1项和就是要找的那一项。

最小值没有被改变保证了找到的最小值一定是正确的。如果数值很大可以采用64位数o(_)o。时间O(n),空间O(1).

 

7楼的,一个64位数存放1M32位整数和绰绰有余。。。。。。

 

题目四:

http://topic.csdn.net/t/20060928/11/5053862.html

1.         任何一个基于“比较”的内部排序的算法,若对6个元素进行排序,则在最坏情况下所需的比较次数至少为____    

  A10               B11           C21                   D36    

   

Answer1:

据严蔚敏数据结构,问题等价于给n个不同的砝码和一台天平要称几次能分辨它们的顺序。

n个记录的序列可能出现的初始状态有n!个,则描述n个记录排序过程的判定树必有n!个叶子节点,若有n个叶子节点,则二叉树的高度至少为log 2 n!,(2为底)+ 1,也即是说必然存在一条长为log 2 n!的路径,求出来n10

 

Answer2

http://topic.csdn.net/u/20090516/21/437e6adb-fffd-4fe3-b900-a3f20f1063da.html

任何一个基于“比较”的内部排序的算法,若对5个元素进行排序,则在最坏情况下所需的比较次数至少为(71)

  (71)A7

  B8

  C21

  D120

  答案:(71)A

解析:对于5个记录的集合任何一个基于“比较”的内部排序的算法的判定树的叶子结点数目为5!,此判定树的树高至少为log25!。由5!=1202^7=1282^6=64可得6 <log25! <7。因此在最坏情况下所需的比较次数至少为7

 

 

 

 

 

题目五:

http://topic.csdn.net/u/20071025/15/9258458F-22D2-4C50-85CD-101705978633.html

一个自然数可以分解为若干个自然数相乘,对于指定自然数n,请求出每种分解自然数之和最小的一个。

说明:不考虑1,若是素数,则是它本身。

例子:如6=2*3,或是它本身,则2+3最小。

限制:无

要求:完成函数

    unsigned int minsum(unsigned int n),n为输入自然数,返回最小的和。

给出思路分析(文字描述),完成代码,并分析你算法的时间复杂度和空间复杂度。

 

Answer1

http://www.cppblog.com/xpcer/archive/2008/09/18/62151.html

一个自然数可以分解为若干个自然数相乘,求出每种分解自然数之和最少的一个。 12=2*2*3,和为7=2+2+3

分析:如果把用穷举法把所有可能的组合计算出来,那无疑是复杂的。 假设a=b*c。其中bc>=2。则a>=2*max{b,c}>=a+b。由此可见a因数分解后的和比a小。显然a的完全因数分解之后的和最小。问题就变成了自然数完全因数分解求和。

 

#include <math.h>

unsigned int minsum(unsigned int n)

{

    unsigned int sum = 0;

    unsigned int div_idx = 2;

    unsigned int sqrt_n=sqrt(n);

   

    while (1)

    {

        if (div_idx > sqrt_n)

            break;

        if (n % div_idx ==0)

        {

            sum += div_idx;

            n /= div_idx;

            sqrt_n = sqrt(n);

        }

        else

            div_idx++;

    }

    return sum+n;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cyf31

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值