我在上次面试中遇到的一个问题是:
设计函数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。
其他回答
容易的:
function f($n) {
if ($n%2 == 0) return ($n+1)*-1;
else return ($n-1);
}
也许是作弊?(python)
def f(n):
if isinstance(n, list):
return -n[0]
else:
return [n,0]
n = 4
print f(f(n))
--output--
-4
这适用于1073741823至1073741822范围:
int F(int n)
{
if(n < 0)
{
if(n > -1073741824)
n = -1073741824 + n;
else n = -(n + 1073741824);
}
else
{
if(n < 1073741823)
n = 1073741823 + n;
else n = -(n - 1073741823);
}
return n;
}
它的工作原理是获取32位有符号整数的可用范围并将其一分为二。函数的第一次迭代将n自身置于该范围之外。第二次迭代检查它是否在该范围之外-如果是,则将其放回该范围内,但使其为负值。
这实际上是一种保留关于值n的额外“位”信息的方法。
使用全局。。。但事实如此?
bool done = false
f(int n)
{
int out = n;
if(!done)
{
out = n * -1;
done = true;
}
return out;
}
你没说他们期望什么样的语言。。。这是一个静态解决方案(Haskell)。这基本上是在搞乱两个最重要的比特:
f :: Int -> Int
f x | (testBit x 30 /= testBit x 31) = negate $ complementBit x 30
| otherwise = complementBit x 30
在动态语言(Python)中要容易得多。只需检查参数是否为数字X,并返回返回-X的lambda:
def f(x):
if isinstance(x,int):
return (lambda: -x)
else:
return x()