我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
当前回答
我认为最大的可能范围是暗示模块化算术解决方案。在一些模基M中,有一个数,当平方等于M-1(等于-1)。例如,如果M=13,5*5=25,25 mod 13=12(=-1)总之,这里有一些M=2**32-3的python代码。
def f(x):
m=2**32-3;
halfm=m//2;
i_mod_m=1849436465
if abs( x ) >halfm:
raise "too big"
if x<0:
x+=m
x=(i_mod_m*x) % m
if (x>halfm):
x-=m
return x;
注意,有3个值不适用于2**31-1、-(2**31-1)和-(2*#31)
其他回答
容易的:
function f($n) {
if ($n%2 == 0) return ($n+1)*-1;
else return ($n-1);
}
用咖啡脚本打高尔夫:
f = (n)-> -n[0] or [n]
我试着打高尔夫,这是罗德里克·查普曼的回答。
无分支: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%。
PHP,不使用全局变量:
function f($num) {
static $mem;
$answer = $num-$mem;
if ($mem == 0) {
$mem = $num*2;
} else {
$mem = 0;
}
return $answer;
}
适用于整数、浮点数和数字字符串!
只是意识到这会做一些不必要的工作,但是,不管怎样
int f(int x){
if (x < 0)
return x;
return ~x+1; //two's complement
}