百度考试题,请赐教!

li1gang11 2007-09-11 02:11:58
1 完成函数
size_t foo(unsigned int *a1, size_t al1, unsigned int* a2, size_t al2)
其中a1和a2都为无符号数组,al1和al2为数组的长度,数组的长度为偶数。
无符号数组由一对数字区间组成。如下例:
a1 为 0,1,3,6,10,20
a2 为 0,1,20,50,4,5
则 a1表示以下区间[0,1] [3,6] [10,20]
a2表示以下区间[0,1] [20,50] [4,5]
则a1,a2的重叠部分为[0,1] [4,5],其长度为2
函数foo要求返回重叠区间的长度。上例中为2.

要求:
详细说明自己的解题思路,说明自己实现的一些关键点。
写出函数foo原代码,另外效率尽量高,并给出代码的复杂性分析。
限制:
al1和al2的长度不超过100万。而且同一个数组的区间可能出现重重叠。
如a1可能为 0,5, 4,8, 9,100, 70,80
使用的存储空间尽量小。


2 多人排成一个队列,我们认为从低到高是正确的序列,但是总有部分人不遵守秩序。如果说,前面的人比后面的人高(两人身高一样认为是合适的),那么我们就认为这两个人是一对“捣乱分子”,比如说,现在存在一个序列:
176, 178, 180, 170, 171
这些捣乱分子对为 <176, 170 >, <176, 171 >, <178, 170 >, <178, 171 >, <180, 170 >, <180, 171 >,
那么,现在给出一个整型序列,请找出这些捣乱分子对的个数(仅给出捣乱分子对的数目即可,不用具体的对)

要求:
输入:
为一个文件(in),文件的每一行为一个序列。序列全为数字,数字间用”,”分隔。
输出:
为一个文件(out),每行为一个数字,表示捣乱分子的对数。

详细说明自己的解题思路,说明自己实现的一些关键点。并给出实现的代码 ,并分析时间复杂度。

限制:
输入每行的最大数字个数为100000个,数字最长为6位。程序无内存使用限制。


二、下面是两道选做题,请根据自己的情况选择其中的一道作答(WEB方向请答第4道,其他职位方向答第3道)。

3
考虑一个在线好友系统。系统为每个用户维护一个好友列表,列表限制最多可以有500个好友,好友必须是这个系统中的其它用户。好友关系是单向的,用户B是用户A的好友,但A不一定是B的好友。

用户以ID形式表示,现给出好友列表数据的文本形式如下:
1 3,5,7,67,78,3332
2 567,890
31 1,66
14 567
78 10000

每行数据有两列,第一列为用户ID,第二列为其好友ID,不同ID间用”,”分隔,ID升序排列。列之间用”t”分隔。


要求:
请设计合适的索引数据结构,来完成以下查询:
给定用户A和B,查询A和B之间是否有这样的关系:B是A的二维好友(好友的好友)。
如上例中,10000为1的二维好友,因为78为1的好友,10000为78的好友。

详细说明自己的解题思路,说明自己实现的一些关键点。并给出实现的伪代码实现建立索引过程和查询过程,并说明空间和时间复杂度。

限制:
用户数量不超过1000万,平均50个好友。

4
有关系模式:User(userId, userName), Article(articleId, userId, title, content),Vote(articleId, score),User为用户关系,Article为用户发表的文章关系,Vote为文章得票关系,title为文章标题、score为得票数。
(1)用SQL语言查询所有没发表过文章的用户名;
(2)用SQL语言查询得票数大于100的所有文章标题,按得票数倒序排列;
(3)用SQL语言查询出发表文章数大于5,文章平均得票数大于100的用户名,按平均得票数倒序排列;
(4)设计这些表的主键、外键和索引,并指出上面三个查询所使用的索引。
(5)当用户数超过1000万,文章数超过1亿时,如何考虑存储及性能的改进和优化?
...全文
5167 80 打赏 收藏 转发到动态 举报
写回复
用AI写文章
80 条回复
切换为时间正序
请发表友善的回复…
发表回复
yunyun050924 2009-10-15
  • 打赏
  • 举报
回复
太长了,直接没办法观看
sql5186 2007-09-19
  • 打赏
  • 举报
回复
3
考虑一个在线好友系统。系统为每个用户维护一个好友列表,列表限制最多可以有500个好友,好友必须是这个系统中的其它用户。好友关系是单向的,用户B是用户A的好友,但A不一定是B的好友。

用户以ID形式表示,现给出好友列表数据的文本形式如下:
1 3,5,7,67,78,3332
2 567,890
31 1,66
14 567
78 10000

每行数据有两列,第一列为用户ID,第二列为其好友ID,不同ID间用”,”分隔,ID升序排列。列之间用”t”分隔。


要求:
请设计合适的索引数据结构,来完成以下查询:
给定用户A和B,查询A和B之间是否有这样的关系:B是A的二维好友(好友的好友)。
如上例中,10000为1的二维好友,因为78为1的好友,10000为78的好友。


对于给定的A,B 按照好友ID是B的分组放到表B中,按照用户ID是A分组放到表A中
然后对于给定的A,B:select A.* from A,B WHERE B.用户ID=A.好友ID
li1gang11 2007-09-19
  • 打赏
  • 举报
回复
第2题关键是要最好的时间复杂度???
sql5186 2007-09-19
  • 打赏
  • 举报
回复
2 多人排成一个队列,我们认为从低到高是正确的序列,但是总有部分人不遵守秩序。如果说,前面的人比后面的人高(两人身高一样认为是合适的),那么我们就认为这两个人是一对“捣乱分子”,比如说,现在存在一个序列:
176, 178, 180, 170, 171
这些捣乱分子对为 <176, 170 >, <176, 171 >, <178, 170 >, <178, 171 >, <180, 170 >, <180, 171 >,
那么,现在给出一个整型序列,请找出这些捣乱分子对的个数(仅给出捣乱分子对的数目即可,不用具体的对)
这个问题解决方法主要是从前向后比较:第一个数据和后面的所有的比较,第2个数据也是。。。。
sql5186 2007-09-19
  • 打赏
  • 举报
回复
1 完成函数
首先把两个数组中本身重合的区间变小或去掉
比如:0 ,3 ,4, 8,3,5,6,9我们就可以先把数组简化为0,3,4,8,8,9(因为[3,5]已经在这个区间了,[6,9]中也包含已经存在的区间[6,8])
然后判断重复区间的方法:比如[a,b],[c,d] 如果(a-d)*(b-c)<0则存在重复的区间,这样可以计算重复的区间:abs(abs(b-d)-abs(a-c))
heonker 2007-09-18
  • 打赏
  • 举报
回复
结果:
arr1:0,1,3,6,10,21,
arr2:0,1,4,5,15,20,
maxarr1:21
maxarr2:20
重叠区间数:3
arr1: 1,1,0,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,
arr2: 1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,
newarr:1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,
但是这个函数在只有一个数的区间会有问题如
arr1:0,1,3,6,10,21,
arr2:0,1,4,5,21,40,
带解决中
heonker 2007-09-18
  • 打赏
  • 举报
回复
第一题的代码,用vb.net写的,不会C了,哈哈哈
Public Class Form1

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim ar1 As New ArrayList
Dim ar2 As New ArrayList
Dim arrResult As New ArrayList
Dim i As Integer
ar1.Add(0)
ar1.Add(1)

ar1.Add(3)
ar1.Add(6)

ar1.Add(10)
ar1.Add(21)

ar2.Add(0)
ar2.Add(1)

ar2.Add(4)
ar2.Add(5)

ar2.Add(15)
ar2.Add(20)

End Sub

Function compare(ByRef arr1 As ArrayList, ByRef arr2 As ArrayList, ByRef arrResult As ArrayList) As Integer

Dim count, i, j As Integer
Dim ar1Max As Integer
Dim ar2Max As Integer
Dim arrResult1 As New ArrayList
Dim arrResult2 As New ArrayList

ar1Max = Sort(arr1)
ar2Max = Sort(arr2)
System.Console.WriteLine(ar1Max)
System.Console.WriteLine(ar2Max)

For i = 0 To Math.Min(ar1Max, ar2Max)
arrResult1.Add(0)
arrResult2.Add(0)
arrResult.Add(0)
Next

For i = 0 To arr1.Count - 1
For j = arr1(i) To Math.Min(arr1(i + 1), Math.Min(ar1Max, ar2Max))
arrResult1(j) = 1
Next
i = i + 1
Next


For i = 0 To arr2.Count - 1
For j = arr2(i) To Math.Min(arr2(i + 1), Math.Min(ar1Max, ar2Max))

arrResult2(j) = 1

Next
i = i + 1
Next

For i = 0 To arrResult1.Count - 1
If arrResult1(i) = 1 And arrResult2(i) = 1 Then
arrResult(i) = 1
Else
arrResult(i) = 0
End If
Next

Dim blnFST As Boolean = True
Dim blnNT As Boolean = False

For i = 0 To arrResult.Count - 1
If arrResult(i) = 1 Then
If blnFST = True Then
count = count + 1
blnFST = False
Else
Continue For
End If
Else
blnFST = True
End If
Next

arr1 = arrResult1
arr2 = arrResult2

Return count

End Function


Function Sort(ByRef arr As ArrayList) As Integer

Dim i As Integer
Dim aMax As Integer

aMax = arr(1)

For i = 1 To arr.Count - 1
If arr(i) > aMax Then
aMax = arr(i)
End If
i = i + 1
Next

Return aMax

End Function

End Class
heonker 2007-09-18
  • 打赏
  • 举报
回复
第一题:
借用了一下前面的思想:先找出array1和array2的最大数maxarr1,maxarr2
然后建立2个新array,长度为min(maxarr1,maxarr2)初始全为0,然后循环array1和array2
把所有范围置成1,如(2,5)就把从2到5全设成1,超出范围的就到min(maxarr1,maxarr2)为止,然后按与的方法合并2个新数组,最后得到的的数组所有连续为1的部分就是2个array的公共部分,在计算个数。至于时间复杂度,俺不会算。。。
另外一种,还是先找出array1和array2的最大数maxarr1,maxarr2(只计算在偶数位的数),同时记录住所在位置,然后取得和他对应的前点,如(10,25)若25位最大,就取得10,然后在max数组,取得不大于10的最大值(只计算在偶数位的数),如此循环,直到前点数为最小。然后就取出了2个合并好的区间序列,且已经是按从小到大排列,然后循环数组2找出所有前点和后点同时不在的个数,用数组2总数减,得出重叠个数。(如合并后的数组1(1,5,7,8,12,15)数组2(2,3,6,8,10,11)先得到数组1的第一组的最大5,然后在数组2里找到第一个大于5的前点6,在找后点8,比较8和7(数组1中5后面的),如果小于的话则count+1,大于的话在做同前面的操作)
第二题:
求出数组的最小值,且记住所在位置(如176, 178, 180, 170, 171
中,最小为170,位置为3,则count=3,然后去除这个点,在min,得到位置,count+,再去除点,循环直到最后剩余的点为一个,最后的count即为所求

CoffeeCN 2007-09-18
  • 打赏
  • 举报
回复
解第一题的思路相对来说比较简单
例如 a1[0,1] [3,6] [10,20]
a2[0,1] [20,50] [4,5]
重新构造两个数组a'1和a'2,把数字区间标记成单位长度如[0,1]就是单位段1,[3,6]就是单位段4段5段6
重新构造後的两个数组为
a'1 = { 1, 4, 5, 6, 11, ..., 20 };
a'2 = { 1, 5, 21, ..., 50 };
变成这种形式後谁都会做了把,重复出现的数字是1和5,出现的个数就是要求的长度,这种算法不仅能知道所求的长度,还能知道重复的具体段。
这种算法时间和空间复杂度都不是最优
li1gang11 2007-09-18
  • 打赏
  • 举报
回复
大家的第3题还有什么好思想???
li1gang11 2007-09-18
  • 打赏
  • 举报
回复
大家的第3题还有什么好思想???
yihucha166 2007-09-18
  • 打赏
  • 举报
回复
mark
li1gang11 2007-09-17
  • 打赏
  • 举报
回复
最关键的第3题,难道没有知道????求解中。。。。
独孤过儿 2007-09-17
  • 打赏
  • 举报
回复
百度不是有保密协议,严禁泄露吗?楼主不要资格了啊?呵呵
ochinchina 2007-09-17
  • 打赏
  • 举报
回复
第三题:

献丑了

每个用户保存好友Id和被加为好友的用户Id

#include <iostream>
#include <vector>
#include <fstream>
#include <cctype>
#include <assert.h>

using namespace std;

class User {
public:
User( int id );
void addFriend( int id );
void addFriendBy( int id );
bool isMyFriend( int id );
bool addedBy( int id );
void removeFriend( int id );
void removeAddedBy( int id );
const vector< int >& getAddedBy() const {
return addFriendsBy_;
}
int getId() const;
private:
static void insert( int val, vector< int >& v );
static void remove( int val, vector< int >& v );
static bool exists( int val, vector< int >& v );
private:
int id_;
vector< int > myFriends_;
vector< int > addFriendsBy_;
};

User::User( int id )
:id_( id ) {
}

void User::addFriend( int id ) {
insert( id, myFriends_ );
}

void User::addFriendBy( int id ) {
insert( id, addFriendsBy_ );
}

int User::getId() const {
return id_;
}

bool User::isMyFriend( int id ) {
return exists( id, myFriends_ );
}

bool User::addedBy( int id ) {
return exists( id, addFriendsBy_ );
}

void User::removeFriend( int id ) {
remove( id, myFriends_ );
}

void User::removeAddedBy( int id ) {
remove( id, addFriendsBy_ );
}

void User::insert( int val, vector< int >& v ) {
if( v.size() <= 0 ) {
v.push_back( val );
return;
}

int i = 0;
int j = v.size() - 1;

if( val > v[j] ) {
v.push_back( val );
return;
}

while( i <= j ) {
int k = ( i + j ) / 2;
int tmp = v[ k ];
if( val == tmp ) return;
if( val < tmp ) {
j = k - 1;
} else {
i = k + 1;
}
}
vector< int >::iterator iter = v.begin();
iter += i;
v.insert( iter, val );
}

void User::remove( int val, vector< int >& v ) {
if( v.size() <= 0 ) return;

int i = 0;
int j = v.size() - 1;

while( i <= j ) {
int k = ( i + j ) / 2;
int tmp = v[ k ];
if( val == tmp ) {
v.erase( v.begin() + k );
return;
}
if( val < tmp ) {
j = k - 1;
} else {
i = k + 1;
}
}
}


bool User::exists( int val, vector< int >& v ) {
int i = 0;
int j = v.size() - 1;


while( i <= j ) {
int k = ( i + j ) / 2;
int tmp = v[ k ];
if( val == tmp ) return true;
if( val < tmp ) {
j = k - 1;
} else {
i = k + 1;
}
}
return false;
}

class UserManager {
public:
UserManager();
UserManager( const string& fileName );
~UserManager();
void loadFromFile( const string& fileName );
void addFriend( int id, int friendId );
void removeFriend( int id, int friendId );
bool isFriend( int id, int friendId, int level ) const;
private:
User& getUser( int id );
User* findUser( int id ) const;
User* addUser( int id );
private:
vector< User* > users_;
};

UserManager::UserManager() {
}

UserManager::UserManager( const string& fileName ) {
loadFromFile( fileName );
}

UserManager::~UserManager() {
while( !users_.empty() ) {
delete users_.back();
users_.pop_back();
}
}

void UserManager::loadFromFile( const string& fileName ) {
ifstream ifs( fileName.c_str(), ios_base::in|ios_base::binary );
char* buf = new char[ 4096 ];
while( !ifs.eof() ) {
ifs.getline( buf, 4096 );
int i = 0;
int n = strlen( buf );
int j;

for( ; i < n && isspace( buf[ i ] ); i++ );
for( j = i; j < n && isdigit( buf[j] ); j++ );
if( !isspace( buf[j] ) ) continue;
int id ;
int friendId;

if( sscanf( &buf[i], "%d", &id ) != 1 ) continue;

for( i = j + 1; i < n ; i++ ) {
if( buf[i] == ',' ) {
if( sscanf( &buf[j], "%d", &friendId ) == 1 ) {
addFriend( id, friendId );
}
j = i + 1;
}
}
if( sscanf( &buf[j], "%d", &friendId ) == 1 ) {
addFriend( id, friendId );
}
}

delete[] buf;
}

void UserManager::addFriend( int id, int friendId ) {

getUser( id ).addFriend( friendId );
getUser( friendId ).addFriendBy( id );
}

void UserManager::removeFriend( int id, int friendId ) {
getUser( id ).removeFriend( friendId );
getUser( friendId ).removeAddedBy( id );
}
bool UserManager::isFriend( int id, int friendId, int level ) const {
if( level <= 0 ) {
return id == friendId;
}
User* pUser = findUser( friendId );
if( ! pUser ) return false;

const vector<int>& addedBy = pUser->getAddedBy();

vector< int >::const_iterator iter = addedBy.begin();

while( iter != addedBy.end() ) {
if( isFriend( id, *iter, level - 1 ) )
return true;
iter ++;
}
return false;
}

User& UserManager::getUser( int id ) {
User* pUser = addUser( id );
assert( pUser );
return *pUser;
}

User* UserManager::addUser( int id ) {
if( users_.size() <= 0 ) {
User* pUser = new User( id );
users_.push_back( pUser );
return pUser;
}

int i = 0;
int j = users_.size() - 1;

while( i <= j ) {
int k = ( i + j ) / 2;
User *pUser = users_[ k ];
int userId = pUser->getId();
if( id == userId ) return pUser;
if( id < userId ) {
j = k - 1;
} else {
i = k + 1;
}
}

User *pUser = new User( id );
vector<User*>::iterator iter = users_.begin();
iter += i;
users_.insert( iter, pUser );
return pUser;

}
User* UserManager::findUser( int id ) const {
int i = 0;
int j = users_.size() - 1;

while( i <= j ) {
int k = ( i + j ) / 2;
User *pUser = users_[k];
int userId = pUser->getId();
if( id == userId ) return pUser;
if( id < userId ) {
j = k - 1;
} else {
i = k + 1;
}
}

return 0;
}

int main( int args, char** argv ) {
UserManager userManager( "test.txt" );
cout << "1 is friend of 10000:" << userManager.isFriend( 1, 10000, 2 ) << endl;

}
somer 2007-09-17
  • 打赏
  • 举报
回复
3。struct planarnode
{
int planarfriend;
planarnode *next;
}
struct hashnode
{
int userid;
planarnode planarfriendid;
}

以userid为键值建立hash
然后遍历用户的好友id,查找hash的用户id是否存在此id
如果存在存在把此id的所有好友id存入planarfriendid,即二维好友
不存在说明不存在二维好友,
Darren_chen 2007-09-17
  • 打赏
  • 举报
回复
收藏
huanghao1986612 2007-09-15
  • 打赏
  • 举报
回复
第一题每个数组分别搞个位图,某位为0表示该数没被区间覆盖,1表示被覆盖。两个位图一与操作,求1的个数。
第二题用插入排序的思想,排序时不要移动数字(就是不要改变原来数字的排列顺序,不真的排序),仅仅计算要移动的数字个数就行。时间复杂度O(n2),空间O(1).
第三题求教,希望有大牛给个好方法。
crossrowman 2007-09-14
  • 打赏
  • 举报
回复
设第n个数字为d(n)
设第n个数字的逆序对(“捣乱分子”)个数为D(n)
1.求出D(1).
从第一个开始遍历比较,找出第一个数字的所有的逆序对(“捣乱分子”)
2.从第2(n+1)个开始,使其与前一个(n)数字比较:
d(n+1)>=d(n):则 D(n+1)=D(n)
d(n+1)<d(n) :则 D(n+1)=D(n)-1
3.然后把所有的D(n)相加就好

-----------------------------------
假设序列为 4 1 2 3
正确答案应该为 3: <4,1> <4,2> <4,3>

d(n) 4 1 2 3
D(N) 3 2 2 2 =??

愤怒的小蒋 2007-09-14
  • 打赏
  • 举报
回复
马克
加载更多回复(60)

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧