我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
当前回答
怎么样:
f(n) = sign(n) - (-1)ⁿ * n
在Python中:
def f(n):
if n == 0: return 0
if n >= 0:
if n % 2 == 1:
return n + 1
else:
return -1 * (n - 1)
else:
if n % 2 == 1:
return n - 1
else:
return -1 * (n + 1)
Python自动将整数提升为任意长度的longs。在其他语言中,最大的正整数将溢出,因此它将适用于除该整数之外的所有整数。
为了使其适用于实数,您需要替换(-1)中的nⁿ 如果n>0,则为{上限(n);如果n<0},则为下限(n)。
在C#中(适用于任何双精度,溢出情况除外):
static double F(double n)
{
if (n == 0) return 0;
if (n < 0)
return ((long)Math.Ceiling(n) % 2 == 0) ? (n + 1) : (-1 * (n - 1));
else
return ((long)Math.Floor(n) % 2 == 0) ? (n - 1) : (-1 * (n + 1));
}
其他回答
这是rossfabricant答案的C实现。注意,由于我始终使用32位整数,f(f(2147483647))==2147483648,而不是-2147483647。
int32_t f( int32_t n )
{
if( n == 0 ) return 0;
switch( n & 0x80000001 ) {
case 0x00000000:
return -1 * ( n - 1 );
case 0x00000001:
return n + 1;
case 0x80000000:
return -1 * ( n + 1 );
default:
return n - 1;
}
}
如果您将问题定义为允许f()接受并返回int64_t,则会涉及2147483647。当然,switch语句中使用的文字必须更改。
根据您的平台,某些语言允许您在函数中保持状态。VB.Net,例如:
Function f(ByVal n As Integer) As Integer
Static flag As Integer = -1
flag *= -1
Return n * flag
End Function
IIRC、C++也允许这样做。我怀疑他们正在寻找不同的解决方案。
另一个想法是,由于它们没有定义函数第一次调用的结果,因此可以使用奇数/均匀度来控制是否反转符号:
int f(int n)
{
int sign = n>=0?1:-1;
if (abs(n)%2 == 0)
return ((abs(n)+1)*sign * -1;
else
return (abs(n)-1)*sign;
}
所有偶数的幅度加一,所有奇数的幅度减一。两次调用的结果大小相同,但在一次调用中,我们甚至交换了符号。在某些情况下,这不会起作用(-1,max或min int),但它的效果比迄今为止任何其他建议都要好得多。
return x ^ ((x%2) ? 1 : -INT_MAX);
嗯,我既不是数学,也不是编程高手,但这不是很容易吗?
int f(int i) {
static bool b;
if (b) {
b = !b;
return i;
} else {
b = !b;
return -i;
}
}
用大小正值和负值INT_MIN、INT_MAX进行测试,似乎可以。。。如果这是一个问题,可以使线程安全,但这不是任务的一部分。
或者我错过了什么?
JavaScript单行:
function f(n) { return ((f.f = !f.f) * 2 - 1) * n; }