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

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

有什么想法吗?


当前回答

Wolfram语言的解决方案:

f[f[n_]] := -n

应用程序:

In[2]:= f[f[10]]                                                                                                                                                                                                                                                                              
Out[2]= -10
In[3]:= f[10]                                                                                                                                                                                                                                                                                 
Out[3]= f[10]

因为这个问题没有说明f(n)的值,所以f[n]仍然没有赋值。

其他回答

Wolfram语言的解决方案:

f[f[n_]] := -n

应用程序:

In[2]:= f[f[10]]                                                                                                                                                                                                                                                                              
Out[2]= -10
In[3]:= f[10]                                                                                                                                                                                                                                                                                 
Out[3]= f[10]

因为这个问题没有说明f(n)的值,所以f[n]仍然没有赋值。

我想我会先不看别人的答案就试试这个:

#include <stdio.h>
#include <limits.h>
#include <stdlib.h>

int f(int n) {
    if(n > 0) {  
        if(n % 2)
            return -(++n);
        else {
            return (--n);

        }
    }
    else {
        if(n % 2)
            return -(--n);
        else {
            return (++n);

        }
    }
}

int main(int argc, char* argv[]) {
    int n;
    for(n = INT_MIN; n < INT_MAX; n++) {
        int N = f(f(n));

        if(N != -n) {
            fprintf(stderr, "FAIL! %i != %i\n", N, -n);
        }
    }
    n = INT_MAX;
    int N = f(f(n));
    if(N != -n) {
        fprintf(stderr, "FAIL! n = %i\n", n);
    }
    return 0;
}

输出:[无]

这里有一个解决方案,其灵感来自于不能使用复数来解决这个问题的要求或声明。

乘以-1的平方根是一个想法,但似乎失败了,因为-1没有整数的平方根。但是,使用mathematica这样的程序可以得出如下公式

(18494364652+1)模(232-3)=0。

这几乎和平方根为-1一样好。函数的结果必须是有符号整数。因此,我将使用一个修改的模运算mods(x,n),它返回与x模n最接近0的整数y。只有极少数编程语言能够成功地进行模运算,但它很容易被定义。例如,在python中,它是:

def mods(x, n):
    y = x % n
    if y > n/2: y-= n
    return y

使用上面的公式,问题现在可以解决为

def f(x):
    return mods(x*1849436465, 2**32-3)

对于[-231-2231-2]范围内的所有整数,这满足f(f(x))=-x。f(x)的结果也在这个范围内,但当然计算需要64位整数。

这很简单!

每个数字以4为周期映射到另一个数字,其中所需条件成立。

例子:

规则如下:

0→ 0±2³¹ → ±2³¹古怪的→ 甚至,甚至→ -奇数:对于所有k,0<k<2³⁰: (2k-1)→ (2k)→ (-2k+1)→ (-2k)→ (2k-1)

唯一不匹配的值是±(2³¹-1),因为只有两个。必须有两个不能匹配,因为在二进制补码系统中只有四个数字的倍数,其中0和±2³¹已被保留。

在一的补码系统中,存在+0和-0。我们开始了:

对于所有k,0<k<2³⁰: (+2k)→ (+2k+1)→ (-2k)→ (-2k-1)→ (+2k)

从来没有人说过f(x)必须是同一类型。

def f(x):
    if type(x) == list:
        return -x[0]
    return [x]


f(2) => [2]
f(f(2)) => -2