百度笔试题5.1

来源:互联网 发布:女程序员容易老吗 编辑:程序博客网 时间:2024/05/21 04:23

一:编程题

现有一组共计N个固定的集合(N为万量级),每个集合有个从0开始递增的集合ID,每个集合包含1~MTERMM0~100的量级),希望设计一个程序能够持续对外服务,输入是一个TERM数组,输出其中任意一个集合ID(如果该TERM数组包含该集合的所有TERM),如果找不到输出-1。要求:

1  时间复杂度最优,能够在短时间内对大量输入逐个输出

2  实现具体的代码(可以是伪代码),其中常用的数据结构可以采用标准库。

3  给出时间复杂度和空间复杂度。

TERM组合集合的文件格式举例:

TERM_1 空格 TERM_2

TERM_1 空格 TERM_3

TERM_1 空格 TERM_3  TERM_4

输入的为TERM数组(说明:TERM为一个词,可能是中文,固定字符串表示)

Answer1:

A1:判断一个集合中的所有TERM是否在输入数组中,可以使用布隆过滤器。建立位数组大小为100bit,即12.5B

判断集合中的term是否都在数组中,如果都在,那么输出集合的编号。

Answer2:

1. 千万不要写代码 . 伪代码即可, 不然容易陷入写算法, 或者强制算法的坑里面.不利于后面的分析

2. 时间复杂度小. 这个其实应该是考的对于初始状态的把握. 如何构造有序的初始环境的问题. 因为如果完全乱序(集合内变量顺序, 与用于查找时集合本身是否有序), 那就只能直接遍历了, 呵呵 那是不可接受的. 我的考虑是先对集合内进行排序, 再对集合的集合本身进行一个排序. 不过因为题目有单独提出ID, 所以其实是告诉我们, 应该用另外的空间去建立索引

3. 可持续运行, 其实应该是最重要的考点. 重点分析如下:

    1> 由于持续运行, 所以每单次查找的开销应该最小, 所以针对上面说的, 做一个初始的有序环境非常的重要.

2> 同样由于持续运行, 所以有必要考虑动态增删的问题. 因此上面说的, 对于集合的集合的排序, 可以使用RBTREE的方式, 可能会比较好.

 

Answer3:(自己)

如果可以使用标准模板库,那么使用set存储每一个集合,然后建立vecotr<set>存储总集合。查找set中每一个元素是否在term数组中。

这个算法的时间复杂度为:O(M*N*P),Pterm数组的大小。

可以将时间复杂度降到O(M*N),先将term数组的所有元素通过hash函数在标记数组flag中进行标记,然后遍历所有集合,对集合中的term进行hash,查看term是否在flag数组中,如果该集合的term都在flag数组中,那么将这个集合的id输出。

难点是:如何对每一个term进行hashhash函数如何设定。

 

#include "head.h"

 

//查找term数组

 

int IsExist(string term[],int size,string key)

{

       int flag=0;

      for(int i=0;i<size;i++)

         {

           if(key==term[i])

              {

                flag=1;

                break;

              }

         }

 

         return flag;

}

 

void FindID(vector<set<string> > data,string term[],int size)

{

  int flag=0;

  vector<set<string> >::iterator it=data.begin();

  vector<set<string> >::iterator end=data.end();

 

  //遍历每一个集合

  int id=1;

  while(it!=end)

  {

       set<string> cur=*it;

       set<string>::iterator sit=cur.begin();

       set<string>::iterator send=cur.end();

       flag=0;

       //term数组中的查找每一个集合的元素

    while(sit!=send)

       {

        flag=IsExist(term,size,*sit);

        if(0==flag)

               break;

        else

            sit++;

       }

 

       if(1==flag)

              printf("%3d",id);

 

       it++;

       id++;

      

  }

 

 

 

 

  printf("/n");

}

 

#define N 4

void testFindID()

{

  vector<set<string> > data;

  set<string> s1;

  s1.insert("a1");

  s1.insert("a2");

 

  set<string> s2;

  s2.insert("a1");

  s2.insert("a2");

  s2.insert("a3");

  s2.insert("a4");

 

  set<string> s3;

  s3.insert("a2");

  s3.insert("a4");

 

  set<string> s4;

  s4.insert("a2");

  s4.insert("a3");

 

  data.push_back(s1);

  data.push_back(s2);

  data.push_back(s3);

  data.push_back(s4);

 

  string term[N]={"a1","a2","a3"};

  FindID(data,term,4);

}

 

void main()

{

testFindID();

}

 

 

Answer4:(自己)

改进Asnwer3,将term数组的每一个term通过hash,记录每一个元素的位置,然后在遍历每一个集合的时候,就可以将集合中的元素hash来判断这个元素是否在term数组中,改进以后,时间复杂度为OM*N)。

具体的就不写了,下面是使用字符串hash的例子。

#include<iostream>

#include<string>

using namespace std;

const int N=3;

const int MAX = 9973; //哈希表长度

const int len = 30; //字符串的最大长度

 

int Htable[MAX];

char *ch[N]={"abc","def","ghi"};

 

//char ch[MAX][len]; //存储关键字的字符串

//ELF哈希函数

unsigned long Hash(char * key)

{

    unsigned long h = 0;

    while(*key)

    {

        h = (h << 4) + *key++;

        unsigned long g = h & 0xf0000000L;

        if(g)

            h ^= g >> 24;

        h &= ~g;

    }

    return h % MAX;

}

int search(char * key)

{

    unsigned long i = Hash(key);

    while(Htable[i]!=-1)

    {

        if(strcmp(ch[Htable[i]], key) == 0)

            return i;

        i = (i + 1) % MAX;

    }

    return -1;

}

int insert(char * key, int j) //j为关键字在ch中的位置,即索引

{

    unsigned long i = Hash(key);

    while(Htable[i])

        i = (i + 1) % MAX;

       Htable[i] =j;

       printf("%d/n",i);

    return i;

}

 

void main()

{

       int i;

       //初始化hash

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

       {

         Htable[i]=-1;

       }

       //对字符串数组的各元素进行hash

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

       {

         insert(ch[i],i);

       }

 

       //查找

       printf("please input the string to search:");

       char key[100];

       scanf("%s",key);

       int flag=search(key);

       printf("%d/n",flag);

}

 

 

 

 

 

Answer5:

字符串结合位图:

#include "head.h"

 

#define HMAX 65535

#define SHIFT 5

#define MASK 0x1f

#define BITSPERWORD 32

#define HSIZE (HMAX/8+1)

 

unsigned long shash(const char *str)

{

  unsigned long h=0;

  while(*str!='/0')

  {

    h=h*31+*str;

       str++;

  }

 

  return h;

}

 

//使用位图结构实现集合

void sseti(int elem[],int key)

{

  elem[key>>SHIFT] |= 1<<(key&MASK);

}

 

void scleari(int elem[],int key)

{

  elem[key>>SHIFT] &= ~(1<<(key&MASK));

}

 

int sisExist(int elem[],int key)

{

  int flag=0;

  if(elem[key>>SHIFT] & (1<<(key&MASK)) )

         flag=1;

  else

         flag=0;

  return flag;

}

 

void main()

{

       char *pstr[]={"abc","abcd","bce","efg"};

       int size=sizeof(pstr)/sizeof(pstr[0]);

       int i;

       int elem[HSIZE];

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

       {

         elem[i]=0;

       }

 

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

       {

         int h=shash(pstr[i])%HMAX;

         sseti(elem,h);

       }

 

       char str[100];

       printf("please input string:");

       scanf("%s",str);

       int result=shash(str)%HMAX;

       printf("%d/n",sisExist(elem,result));

}

原创粉丝点击