首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 培训 数据库 书店 程序员
中国软件网
欢迎您:游客 | 登录 注册 帮助
  • 一道google的面试题(转自瀚海星云)
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-28 16:39:15 楼主
    输入a_1, a_2, ..., a_n, b_1, b_2, ..., b_n,如何在O(n)的时间,用O(1)的空间,
    将这个序列顺序改为a_1, b_1, ..., a_n, b_n。

    这个问题在瀚海星云上跟出了好几十的跟帖,看看大家有没有什么好的解法!!!
    120  修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-28 16:44:561楼 得分:0
    做个记号
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-28 17:07:432楼 得分:0
    什么存储结构,如果数组的话
    用两个指针,分别指向a1,b1,然后插入
    链表的话,也是直接跟踪插入吧
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • dlyme
    • 等级:
    发表于:2007-12-28 18:06:283楼 得分:0
    http://topic.csdn.net/u/20071203/20/4dd4e19e-37bb-42eb-9b13-a388906d9eab.html
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-29 17:44:154楼 得分:0
    做个记号
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-29 20:21:255楼 得分:0
    留个名
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-29 23:09:046楼 得分:0
    这道题非常简单
    首先我们可以把第二项保存到一个临时变量中, 然后第二项需要有一项来填充, 填充后又空出一项...
    一直计算到需要填入得数字就是第二项即可.
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-29 23:10:167楼 得分:0
    /************************************************************************************************
    输入a_1,  a_2,  ...,  a_n,  b_1,  b_2,  ...,  b_n,如何在O(n)的时间,用O(1)的空间,
    将这个序列顺序改为a_1,  b_1,  ...,  a_n,  b_n。
    1> a_1, b_1, a_3, a_4, a_5, a_6, a_2, b_2, b_3, b_4, b_5, b_6
    2> a_1, b_1, a_2, a_4, a_5, a_6, a_3, b_2, b_3, b_4, b_5, b_6
    ************************************************************************************************/
    #include <iostream>

    using namespace std;

    void order(int* p, int size)
    {
    if( size % 2 != 0 ¦ ¦ size <= 2) // 两项以内不需要移动
    return;

    // 首先把第二个数取出来, 这样第2项就空出来了, 然后计算应该哪一项要移到第二个位置;
    // 这样移动后又空出一项..., 一直计算到正好要填上得就是第二项, 结束移动
    int temp = p[1];
    int index = -1; // 用于保存要移到空位置得项得索引
    index = size / 2;
    p[1] = p[index];

    while(index != 1)
    {
    if(index % 2 == 0) // 需要把a中某一项移入
    {
    p[index] = p[index / 2];
    index = index / 2;
    }
    else
    {
    p[index] = p[index / 2 + size / 2];
    index = index / 2 + size / 2;
    }
    }
    if(index == 1)
    p[index] = temp;
    else
    cout < < "error";
    }

    void testOrder()
    {

    int pp[] = {101, 102, 103, 104, 105, 106, 107, 201, 202, 203, 204, 205, 206, 207};
    order(pp, 14);

    for(int i = 0; i < 4; i++)
    cout < < pp[i] < < " ";
    }

    void main()
    {
    testOrder();
    getchar();
    }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-29 23:13:018楼 得分:0
    上面打印结果得时候出了点错误, 应该是
    for(int i = 0; i < 14; i++)
    cout  < <  pp[i]  < <  "  ";

    运行结果:
    101 102 201 202 103 203 104 204 105 205 106 206 107 207
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-29 23:14:079楼 得分:0
    看了下前面得连接, 方法好像太玄了...
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-29 23:16:1110楼 得分:0
    按照上面得算法, 每次正好移动一个数, 移动size - 2次算出最后结果, 不需要递归, 只需要一个临时变量
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-29 23:18:4211楼 得分:0
    晕, 前面代码示例开头得注视是错得, 忘记了去掉:(
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 00:35:0912楼 得分:0
    to imlmm:
    {101,  102,  103,  104,  105,  106,  107,  201,  202,  203,  204,  205,  206,  207};
    运行结果:
    101  102  201  202  103  203  104  204  105  205  106  206  107  207

    看来你可能题目理解错了
    正确的结果应该是:
    101 201 102 202 103 203....
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 00:58:1313楼 得分:0
    不好意思,疏忽了下,第一个点放错了地方,temp中的临时数据处理错误。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 00:58:5314楼 得分:0
    void  order(int*  p,  int  size)
    {
    if(  size  %  2  !=  0  ¦ ¦  size  <=  2)  //  两项以内不需要移动
    return;

    //  首先把第二个数取出来,  这样第2项就空出来了,  然后计算应该哪一项要移到第二个位置;
    //  这样移动后又空出一项...,  一直计算到正好要填上得就是第二项,  结束移动
    int  temp  =  p[1];
    int  index  =  -1;  //  用于保存要移到空位置得项得索引
    index  =  size  /  2;
    p[1]  =  p[index];

    while(index  !=  1)
    {
    if(index  %  2  ==  0)  //  需要把a中某一项移入
    {
    if(index / 2 == 1)
    p[index] = temp;
    else
    p[index]  =  p[index  /  2];
    index  =  index  /  2;
    }
    else
    {
    if((index / 2 + size / 2) != 1)
    p[index]  =  p[index  /  2  +  size  /  2];
    else
    p[index] = temp;
    index  =  index  /  2  +  size  /  2;
    }
    }
    if(index  !=  1)
    cout  < <  "error";
    }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 01:00:0915楼 得分:0
    现在运行结果是:
    101  201  102  202  103  203....
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 01:01:3116楼 得分:0
    第一个点放错位置,正好使得1,2两个点弄反了。。。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 01:37:1317楼 得分:0
    imlmm正解。
    我本来想用递归方法的。
    发现这样的时间复杂度是O(nlogn),空间复杂度是O(1),不合要求。
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 12:16:4218楼 得分:0
    mathe再数据结构与算法版不是给出过解答了马
    http://topic.csdn.net/u/20071203/20/4dd4e19e-37bb-42eb-9b13-a388906d9eab.html
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 12:28:5619楼 得分:0
    to imlmm
    你的程序运行了吗?
    你自己先运行一下看看结果对不对
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    • 39457760
    • 等级:
    发表于:2007-12-30 13:40:5320楼 得分:0
    n为以下这些数时,都不正确
    4 5 8 9 11 12 13 14 16 17 18 20 21 22 23 24 25 26 28 29 32 33 35 36 37 38 39 40
    41 43 44 45 46 47 48 49 50 52 53 55 56 57 58 59 60 61 62 63 64 65 67 68 69 71 72
    73 74 76 77 78 79 80 81 83 84 85 86 88 89 92 93 94 95 96 97 98
    测试代码
    C/C++ code
    void test() { for(int j=1; j<100;j++) { int N = j; int* a = new int[2*N]; for(int i=0; i<N; i++) { a[i]=i+1; a[N+i]=-(i+1); } order(a,2*N); if(!check(a,2*N)) { cout<<N<<" "; } delete[] a ; } }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 17:15:4621楼 得分:0
    貌似不对的,当移动到B1时就移回了原来的空位(第一次移动A1的空位),大概这个算法也也就结束了,而又不能保证最好移动B1.
    我想理解简单点,就当是数组吧,但可能是个结构数组,所以要求原地算法(不然太费空间),申请点空间做点其他标志应该允许吧.不知道LZ是不是这意思
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 17:15:5822楼 得分:0
    貌似不对的,当移动到B1时就移回了原来的空位(第一次移动A1的空位),大概这个算法也也就结束了,而又不能保证最好移动B1.
    我想理解简单点,就当是数组吧,但可能是个结构数组,所以要求原地算法(不然太费空间),申请点空间做点其他标志应该允许吧.不知道LZ是不是这意思
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 20:52:0823楼 得分:0
    基本思路:在数组N中,N[0]和N[2*num-1]这两个不用变,N[1]和N[2]交换,然后N[1]和N[4],N[1]和N[8]....然后是N[3]和N[6]?
    N[3]和N[12],N[3]和N[18]...这就有规律了,总是奇数位分别与该位的2倍,4倍,8倍,16倍...位交换,如果该倍数大于总长就取模
    直到该倍数取模后的值与原来相等就找下一个奇数位。但是这个过程要先空跑一遍,因为如果可能交换到某步时已经达到最终目标,
    再走下去就会错了。所以要先找到循环到哪一位就可结束了。

    C/C++ code
    #include "Stdio.h" #include "Conio.h" int main(void) { int n[]={1,2,3,4,5,6,7,8,9,10,20,30,40,50,60,70,80,90}; int i,j=2,temp,num=9,max=0; for(i=1;i<num;i+=2){ /*先空跑一遍*/ while((i*j)%(2*num-1)!=i){ max++; j*=2; } j=2; if (max>2*num-3) break; } pp: max=i; /*MAX-2是最大位,由于下面那个循环用了i<max,所以不用max=i就行了*/ for(i=1;i<max;i+=2){ while((i*j)%(2*num-1)!=i){ temp=n[i]; n[i]=n[(i*j)%(2*num-1)]; n[(i*j)%(2*num-1)]=temp; j*=2; } j=2; } for(i=0;i<2*num;i++) printf("%d ",n[i]); getch(); return 0; }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2007-12-30 20:54:0624楼 得分:0
    上面写错了一句,应该是N[3]和N[6],N[3]和N[12],N[3]和N[24]...交换
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-01 18:25:5125楼 得分:0
    我来出另一道题吧
    有一个数组长度为 N, 前面 0-M 段已按升序排好了,后面 M+1 - N 段也按升序排好了。
    现在需要对整个数组进行排序。
    时间复杂度为 O(N) ,额外的空间复杂度为 O(1)

    www.mbsxx.cn
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-06 14:29:1826楼 得分:0
    贴一个,不算太好,最好的应该是2N-2次置换,
    theta置换高不太懂
    比如N=5时
    (1)(2 3 5 9 8 6)(47)(10)
    N=6
    (1)(2 3 5 9 6 11 10 847)(12)


    我写了一个算法不算太好的
    C/C++ code
    void main() { int arr[2*N+1]={0,1,2,3,4,5,6,7,8,9,10}; ReOrder(arr,5); } void ReOrder(int *arr,int n) { if(n == 1) { return ;//do nothing; } for(int m=2;m<n;m++) { int temp = arr[2]; for(int k =2;k<2*m-2;k+=2) { arr[k] = arr[k+2]; } arr[2*m-2] = arr[2*m-1]; arr[2*m-1] = temp; } }
    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-06 14:48:3527楼 得分:0
    不太会贴这个,重新贴下,
    C/C++ code
    void ReOrder(int *arr,int n) { //第0单元无效,用作临时变量 if(n == 1) { return ;//do nothing; } for(int m=2;m<=n;m++) { arr[0] = arr[2]; for(int k =2;k<2*m-2;k+=2) { arr[k] = arr[k+2]; } arr[2*m-2] = arr[2*m-1]; arr[2*m-1] = arr[0]; } } void main() { const int N =6; int arr[2*N+1]={0,1,3,5,7,9,11,2,4,6,8,10,12}; //{0,1,2,3,4,5,6,7,8,9,10}; ReOrder(arr,N); }

    修改 删除 举报 引用 回复
    进入用户个人空间
    加为好友
    发送私信
    在线聊天
    发表于:2008-01-07 17:29:1028楼 得分:0
    C/C++ code
    #include <stdio.h> #define N 10 int num[N * 2]; void disp() { int i; for(i = 0; i < 2 * N; i++) { printf("%03d ", num[i]); } printf("\n"); } void arrange() { unsigned i, n = N * 2 - 1; int t; i = n - 2; t = num[i]; num[i] = num[i + 1]; while(i != n - 1) { if