我在上次面试中遇到的一个问题是:

设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。

有什么想法吗?


当前回答

我试着打高尔夫,这是罗德里克·查普曼的回答。

无分支:74个字符

int f(int i){return(-((i&1)<<1)|1)*i-(-((i>>>31)<<1)|1)*(((i|-i)>>31)&1);}

带有分支,Java风格:58个字符

int f(int i){return i==0?0:(((i&1)==0?i:-i)+(i>0?-1:1));}

带分支,C样式:52个字符

int f(int i){return i?(((i&1)?-i:i)+(i>0?-1:1)):0;}

经过快速但有效的基准测试后,分支版本在我的机器上的速度提高了33%。(正数和负数的随机数据集,足够的重复,并防止编译器在预热时优化代码。)考虑到非分支版本中的操作数量以及可能的良好分支预测,这并不奇怪,因为函数被调用了两次:f(f(i))。当我将基准更改为度量:f(I)时,分支版本只快28%。我认为这证明了分支预测在第一种情况下确实有一些好处。更多证明:当使用f(f(f)(f(i)))进行测试时,分支版本的速度会快42%。

其他回答

我希望你改变2个最高有效位。

00.... => 01.... => 10.....

01.... => 10.... => 11.....

10.... => 11.... => 00.....

11.... => 00.... => 01.....

正如你所看到的,这只是一个补充,省去了进位。

我是怎么得到答案的?我的第一个想法就是需要对称。4转回到我开始的地方。起初我想,这是20比特的格雷码。然后我觉得标准二进制就足够了。

创建许多解的一种方法是注意,如果我们将整数划分为两个集合S和R

那么我们可以如下创建f:

如果x在R中,则f(x)=g(x)

如果x在S中,则f(x)=-invg(x)

其中invg(g(x))=x,所以invg是g的逆函数。

上面提到的第一个解决方案是分区R=偶数,R=奇数,g(x)=x+1。

我们可以取任意两个无限集合T,P s.T T+U=整数集合,取s=T+(-T),R=U+(-U)。

然后-S=S和-R=R通过它们的定义,我们可以将g取为从S到R的任何1-1对应关系,这必须存在,因为这两个集合都是无限的和可数的。

因此,这将为我们提供许多解决方案,但并非所有解决方案都可以编程,因为它们不会被有限地定义。

例如:

R=可被3整除的数字,S=不可被3除的数字。

然后我们取g(6r)=3r+1,g(6r+3)=3r+2。

const unsigned long Magic = 0x8000000;

unsigned long f(unsigned long n)
{    
    if(n > Magic )
    {
        return Magic - n;
    }

    return n + Magic;
} 

0~2^31

作为一名数学家,我想分享我对这个有趣问题的看法。我认为我有最有效的解决方案。

如果我没记错的话,只需翻转第一位,就可以将有符号的32位整数取反。例如,如果n=1001 1101 1110 1011 1110 0000 1110 1010,则-n=0001 1101 11101 1011 11100 0000 1110 010。

那么,我们如何定义一个函数f,它接受一个带符号的32位整数,并返回另一个有符号的32位数整数,该函数的属性是:接受两次f与翻转第一位相同?

让我重新表述这个问题,而不提整数之类的算术概念。

我们如何定义一个函数f,它接受长度为32的一系列0和1,并返回长度相同的一系列零和1,同时具有两次接受f与翻转第一位相同的性质?

观察:如果你能回答32位情况的上述问题,那么你也可以回答64位情况、100位情况等。你只需将f应用于前32位。

现在,如果你能回答2位案例的问题,哇!

是的,改变前2位就足够了。

这是伪代码

1. take n, which is a signed 32-bit integer.
2. swap the first bit and the second bit.
3. flip the first bit.
4. return the result.

备注:步骤2和步骤3可以概括为(a,b)-->(-b,a)。看起来很眼熟?这应该会让你想起平面的90度旋转以及乘以-1的平方根。

如果我只是单独展示了伪代码,而没有冗长的前奏,那么它看起来就像脱口而出的兔子,我想解释一下我是如何得到解决方案的。

这个是Python中的。适用于n的所有负值:

f = abs