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

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

有什么想法吗?


当前回答

这个怎么样?

int nasty(int input)
{
    return input + INT_MAX/2;
}

其他回答

const unsigned long Magic = 0x8000000;

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

    return n + Magic;
} 

0~2^31

使用循环置换方法来实现这一点。

-b a b-a

a b-a-b

在微不足道的情况下f(0)返回0

对不起,我的电话回答很粗糙,28日后我将发布完整版本(现在正在检查…)简单地说,假设f(n)是一个循环排列,问题是如何构造它。

定义fk=f(f(f)f(…f(n))))(k fs)情况k=20.微不足道的情况f(0)返回01.分组,在情况k=2时,分组:{0} {1,2} {3,4} ... {n,n+1 |(n+1)%2=0}注意:我只使用Z+,因为结构不需要使用负数。2.构造排列:如果n%2=0,那么a=n-1 b=n如果n%2=1,则a=n b=n+1

这将产生相同的排列,因为n和f(n)在同一组中。

注意排列为P返回P(n)

对于k=2t,只做上面相同的事情,只做MOD k。对于k=2t-1,虽然该方法有效,但毫无意义,啊?(f(n)=-n正常)

利用JavaScript异常。

function f(n) {
    try {
        return n();
    }
    catch(e) { 
        return function() { return -n; };
    }
}

f(f(0))=>0f(f(1))=>-1

使用问题中给出的信息,您可以

从2-完成转换为符号位表示如果设置了最后一位,则翻转符号位和最后一位;否则,只翻转最后一位转换回2-完成。

所以你基本上是奇数->偶数->奇数或偶数->奇数->偶数,只对偶数更改符号。唯一不适用的数字是-2^31

代码:

function f(x) {
  var neg = x < 0;
  x = Math.abs(x) ^ 1;
  if (x & 1) {
    neg = !neg;
  }
  return neg ? -x : x;
}

这是一个C/C++解决方案,它不使用任何按位运算符,也不需要任何数学库,尽管这有点作弊。。。

double f(double n)
{
    if (n == (double)(int)n)
        return n + 0.5;
    else
        return -(n - 0.5);
}

这适用于所有32位整数,只有一个异常0x80000000(因为它的相反值不能存储在32位整数系统中)。f(f(n))==-n将始终为真,除非在这种情况下。

不过,我相信有一种更简单、更快的方法来实现它。这只是我第一个想到的。