广东北电长沙站的程序笔试题

来源:互联网 发布:php开发oa系统要多久 编辑:程序博客网 时间:2024/05/17 07:53

我没去参加笔试,但据比木同学说,广电的笔试很基础,总共就四道题:1、josephus数小孩问题。2、二分查找法。3、用栈实现递归。4、有关通信、网络方面的汉译英、英译汉。

用栈实现递归,我以前专门写过一篇文章。读者可以去翻来看看。现在,我自己来解答前两个问题。

1、josephus问题的描述:编号是1,2,……,n的n个人按照顺时针方向围坐一圈,每个人只有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始顺时针方向自1开始顺序报数,报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。设计一个程序来求出出列顺序。

解这道题有两种方法,一种是递归法、一种是选代法。给出程序:

//////////////////////////////////
//递归法求解joseph问题,
//////////////////////////////////
//m:第一次的报数次数
//pos:报数的起始位置
//A[][2]:一个二维数组,A[i][0]存放成员的编号,A[i][1]存放成员的密码
//n:成员个数
void  joseph_1(int m, int pos, int A[][2], int n)
{
    
//base case
    if (n == 1)
    {
        cout 
<<"最后一个离开的是"<<A[0][0]<<""<<endl;
        
return;
    }

    
//根据m值,求出将要离队的成员在数姐中的位置
    
//考因为是循环数数,故用求模法
    int out = (pos + m -1)%n;

    
//根据离队成员的密码,决定下一次偏移量
    m = A[out][1];
    
    
//离队的成员编号
    int num = A[out][0];

    
//离队处理
    cout <<"成员"<<num<<"号离队"<<endl;

    
//离开后,该成员后面的所有成员向前移动一位
    for (int i=out; i<n-1; i++)
    {
        A[i][
0= A[i+1][0];
        A[i][
1= A[i+1][1];
    }

    
//对下一次进行处理
    joseph(m, out,A, n-1);

}
////////////////////////////////
//迭代法求解joseph问题
///////////////////////////////
void joseph_2(int m, int pos, int A[][2], int n)
{
    
int out;
    
while (n >1)
    {
        
//离队的位置
        out = (pos + m -1)%n;

        
//下一次离队的偏移量
        m = A[out][1];

        
//离队公告
        cout <<"成员"<<A[out][0]<<"号离队"<<endl;

        
//紧凑队伍
        for (int i=out; i<n-1; i++)
        {
            A[i][
0= A[i+1][0];
            A[i][
1= A[i+1][1];
        }

        
//下一次计数的起始位置
        pos = out;

        
//人数减1
        n--;
    }
    
    cout 
<<"最后一位离队的成员是"<<A[0][0]<<""<<endl;
    
return;
}
//提供测试数据
int A[7][2= 
    {
        {
1,3},{2,1},{3,7},{4,2},{5,4},{6,7},{7,4}
    };

2、二分查找法,我一直觉得二分查找法,是一种非常优美的方法,写起来非常漂亮:

//////////////////////////
//二分查找法
//////////////////////////
//A[]:一个已经从小到大排好序的数组
//n:元素个数
//key:欲查找的关键码
//如果找到,返回关键码所在的下标,否则返回n
int binarySearch(int A[], int n, int key)
{
    
//数组边界
    int left = -1;    
    
int right = n;    

    
//当left == right-1时,边界中间已经没有元素了。
    while (left < right-1)
    {
        
int mid = (left + right)/2; //中间点
        if (key < A[mid])
            right 
= mid;
        
if (key == A[mid])
            
return mid;    //找到了
        else 
            left 
= mid;
    }

    
//没有找到
    return n;
}