[IT码农相关]来道高端的面试题

  • m
    mirokuneal
    今天看见一道题,令我叹为观止

    第一问:(这个是经典题,相信不少人都会)
    一个数组,其中只有一个数出现了一次,另外其他数均出现两次,请找出这个出现一次的数, 要求O(n)的时间复杂度和O(1)的空间复杂度
    比如:输入[2, 2, 3, 4, 3, 1, 4] 输出 1

    第二问,这个就高端了: (注意是这一问高端)
    一个数组,其中只有一个数出现了一次,另外其他数均出现三次,请找出这个出现一次的数, 要求O(n)的时间复杂度和O(1)的空间复杂度
    比如:输入[2, 3, 2, 4, 2, 3, 3] 输出 4

    [本帖最后由 mirokuneal 于 2011-3-18 03:52 编辑]
  • 分不清雨水泪水
    这题都快考烂了。。。。
    请看《编程之美》一书
  • 7
    788414
    这个不难...
  • s
    sectionboy
    谁来看看这是干嘛的:D
    cwd
    xor ax,dx
    sub ax,dx

    [本帖最后由 sectionboy 于 2011-3-16 13:02 编辑]
  • 子山
    这是入门级

    楼主你太嫩了,挨踢行业不适合你
  • 分不清雨水泪水
    通常解法是利用hashtable,伪码:

    for ( i : arr ){
    if( hash表中存在此元素)
    从hash表中删除此元素
    else
    将此元素放入hash
    }
    一趟循环处理完后,hash表应该只有一个元素,就是那个出现一次的数,输出即可

    附加问题同理,处理一下hash判断部分即可

    BTW:这不是最优解
  • 死命遭唤
    我怎么记得在沙特那个人写的书里有这种问题得解法。。
  • 保密
    頭像不錯, 順便問最優解.
  • C
    Crusher
    +65535
  • l
    leonWong
    posted by wap

    这题高端在什么地方啊?
  • z
    zhangu2
    就是个考hash table或hash map的东西,都烂大街了。。。
  • 分不清雨水泪水
    最优解4L贴了,用异或,相同的数字异或完为0,所以所有数组中的数字异或的结果就是那个只出现一次的数
  • m
    mirokuneal
    楼上都是神

    关键是第二个问题,o(n)时间, o(1)常数空间怎么做?

    本帖最后由 mirokuneal 于 2011-3-16 13:31 通过手机版编辑
  • h
    hailfruhner
    .......................
  • 离神最近的人
    这个牛逼,没想到

    第二个怎么做?

    [本帖最后由 离神最近的人 于 2011-3-16 14:24 编辑]
  • E
    Eclipses
    传统做法是6楼说的,不过如果先对数组排序后遍历会不会效率高点》?
  • 神之一技
    异或一把就行
  • f
    ffcactus
    想了一会, 还是不明白, 什么叫“所有数组中的数字异或”?
  • f
    fuckmic
    如果输入有误呢?不考虑容错吗?
  • m
    mirokuneal
    我擦,你这个复杂度太高了,还不如直接sort
  • m
    mirokuneal
    这题高端就高端在第二问
    一堆人看到第一问就高潮了(第一问确实是经典题),直接忽视第二问,实在不知道说什么好
    给个第二问的答案吧:
    复制内容到剪贴板
    代码:
    int main(){
    int B[] = {1,1,1,3,3,3,20,4,4,4};
    int ones = 0 ;
    int twos = 0 ;
    int not_threes;
    int x,i ;

    for( i=0; i< 10; i++ )
    { x = B;
    twos |= ones & x ;
    ones ^= x ;
    not_threes = ~(ones & twos) ;
    ones &= not_threes ;
    twos &= not_threes ;
    }

    printf("\n unique element = %d \n", ones ); return 0;
    }
    [本帖最后由 mirokuneal 于 2011-3-18 03:54 编辑]
  • v
    voidstar
    各种与 或 异或
  • n
    nintenyun
    复制内容到剪贴板
    代码:
    [本帖最后由 nintenyun 于 2011-3-18 13:01 编辑]
  • 阿弄
    oracle數據庫表示沒難度
    --set serveroutput OFF
    declare
    v_return varchar2(10000):='2,3,2,4,2,3,3';
    v_b number;
    i number:=1;
    begin

    v_return:=','||v_return||',';

    loop

    select instr(v_return,','||substr(v_return,instr(v_return,',',1,i)+1,instr(v_return,',',1,i+1)-instr(v_return,',',1,i)-1)||',',1,2)
    into v_b from dual;

    if v_b=0 then

    dbms_output.put_line('test='||substr(v_return,instr(v_return,',',1,i)+1,instr(v_return,',',1,i+1)-instr(v_return,',',1,i)-1));
    exit;

    end if;

    i:=i+1;

    end loop;

    end;
  • 阿弄
    如果是表中的一列數就更容易
    declare
    v_return varchar2(100);
    begin

    select a
    into v_return
    from x_table group by a having sum(1)=1;--

    dbms_output.put_line('test='||v_return);

    end;
  • h
    hourousha
    我觉得挺有难度,因为你得证明这个方法的时间复杂度是O(n),而空间复杂度是O(1)……
  • 流浪的枪骑兵
    惭愧,没能看懂,能否注释一下?
  • 阿弄
    我并不是程序员,只不过因为职业缘故经常需要看或者写PLSQL代码,看你字面的意思是有更高效率的写法,那么请教了
  • m
    mirokuneal
    主要问题是SQL的每次查询不是O(1)的时间复杂度
  • b
    bwl3b
    说白了,第一、二问以及类似的第 X 问解法是通的
    MN+1 个数,N 个数出现 M 次,1 个数出现 1 次
    则任意以一种 K 进制(要求 K<=M)表达这些数、并作不进位加法之后,各位上的结果分别 mod M 就完事
    你看不懂的这段代码,是以 2 进制表示数,做不进位加法,每个位上只保留 mod 3 的结果
    这种属于一通百通的量产面试题……

    [本帖最后由 bwl3b 于 2011-3-19 01:59 编辑]
  • e
    eos
    我想知道列出从1到一千亿里所有的质数这个程序咋编
  • m
    mirokuneal
    是以 2 进制表示数,做不进位加法,每个位上只保留 mod K 的结果
    这个有通用解法么?
  • m
    mirokuneal
    基本原理是ones里面存出现过一次数的bit位(出现2次的会被异或掉)

    twos里面存bit出现过两次数的位(x与上ones的结果,就是出现两次的bit位,加入twos里面)

    当ones和twos里面相同位都为1时,说明这个bit位出现了3次
    把这些bit位从ones和twos里面剔除

    最后ones里面就是仅仅出现过一次的bit位,就是最后结果
  • b
    bwl3b
    是 mod M,不是 mod K……

    如果 M 固定(而非输入的参数),可以像上面这个同学一样手动实现“在线的”二进制加法和取模操作
    实际上空间效率是 O(log(M)),时间效率是 O(L*log(M))(L=N*M+1,即输入数据数的个数)
    因为 M 固定,所以看起来是 O(1)::O(L)

    如果 M 不固定,分三种情况
    1. 知道 N 的范围即 N<=NN,那么可以手动实现“在线”二进制加法、全部输入完毕后再统一取模,效率是 O(log(NN))::O(L*log(NN))
    2. 不知道 N 的范围,但知道 M 的范围即 M<=MM,此时需要蛋疼的高端人士手动实现“在线的”二进制加法和取模,如果能实现,效率是 O(log(MM))::O(L*log(MM))
    3. 通用的慢解法,需要知道所有数的范围(即最大值不超过 H),此时令 K=M(此前 K 一直等于 2),把每个输入的数都转化到 M 进制下,轻松实现“在线”加法(不需要搞取模操作了),效率是 O(log(H))::O(L*log(H))
  • 离神最近的人
    半懂,求详细资料

    不进位加法,二进制下不就是将两数异或么;然后逐位对M取模,在K(进制)<M的情况下,每位都不变。那按你的说法,岂不是全部异或一遍就OK了?貌似不对啊

    [本帖最后由 离神最近的人 于 2011-3-19 10:16 编辑]
  • b
    bwl3b
    加法
    [0,1]+[0,1]=[1,0]
    异或
    [0,1]+[0,1]=[0,0]
    不进位加法
    [0,1]+[0,1]=[0,2]
    这个“2”怎么表示呢?
    在上面那个同学的程序里,是用一个两位二进制数 [two_i,one_i] 来表示的,这里 two_i 是他那个变量 twos 的对应二进制位
    同时这个同学做了在线的 mod 3 操作(就是每加完一次就通过调整 twos ones 做 mod 3)

    举个直观的例子,输入为 {1,1,3,3,1,3,2,7,7,7}
    二进制视角为 [0,0,1]*3,[0,1,1]*3,[1,1,1]*3,[0,1,0]*1
    全部加起来为 [3,7,9]
    每个位对 M=3 取模 [0,1,0]
    于是得到“2”
  • 离神最近的人
    原来你的“不进位加法”是这个意思,理解错了
  • m
    mirokuneal
    关键是怎么用代码实现?