我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
当前回答
我认为这些问题的答案最好用图表直观地解释。当我们忽略零时,我们可以将整数分成4个数的小集合:
1 → 2 3 → 4 5 → 6
↑ ↓ ↑ ↓ ↑ ↓ ...
-2 ← -1 -4 ← -3 -6 ← -5
这很容易翻译成代码。注意,偶数改变符号,奇数增加或减少1。在C#中,它看起来像这样:
public static int f(int x)
{
if(x == 0)
return 0;
if(x > 0)
return (x % 2 == 0) ? -x+1 : x+1;
// we know x is negative at this point
return (x % 2 == 0) ? -x-1 : x-1;
}
当然,您可以通过使用巧妙的技巧来缩短此方法,但我认为这段代码最好地解释了它本身。
然后是范围。32位整数的范围从-2^31到2^31-1。数字2^31-1、-2^31-1和-2^31超出了f(x)的范围,因为缺少数字2^31。
其他回答
本质上,函数必须将可用范围划分为大小为4的循环,其中-n位于n循环的另一端。但是,0必须是大小为1的循环的一部分,否则0->x->0->x!=-x.因为0是单独的,所以在我们的范围内必须有3个其他值(其大小是4的倍数)不在具有4个元素的正确循环中。
我选择这些额外的奇怪值为MIN_INT、MAX_INT和MIN_INT+1。此外,MIN_INT+1将正确映射到MAX_INT,但会被卡在那里而不能映射回来。我认为这是最好的妥协,因为它有一个很好的特性,即只有极端值不能正常工作。此外,这意味着它将适用于所有BigInt。
int f(int n):
if n == 0 or n == MIN_INT or n == MAX_INT: return n
return ((Math.abs(n) mod 2) * 2 - 1) * n + Math.sign(n)
Tcl:
proc f {input} {
if { [string is integer $input] } {
return [list expr [list 0 - $input]]
} else {
return [eval $input]
}
}
% f [f 1]
-1
按照其他一些答案的思路。。。如果它是一个整数,则返回一个返回该数字负数的命令。如果不是数字,请对其求值并返回结果。
F#
let f n =
match n with
| n when n % 2 = 0 -> -n + System.Math.Sign n
| _ -> n - System.Math.Sign -n
其中n使得System.Int32.MinValue<n<System.Int32.MaxValue。
int f(int n)
{
static long counter=0;
counter++;
if(counter%2==0)
return -n;
else
return n;
}
Python 2.6:
f = lambda n: (n % 2 * n or -n) + (n > 0) - (n < 0)
我意识到这对讨论毫无帮助,但我无法抗拒。