我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
当前回答
这个怎么样:
do
local function makeFunc()
local var
return function(x)
if x == true then
return -var
else
var = x
return true
end
end
end
f = makeFunc()
end
print(f(f(20000)))
其他回答
对于所有32位值(注意,-0是-2147483648)
int rotate(int x)
{
static const int split = INT_MAX / 2 + 1;
static const int negativeSplit = INT_MIN / 2 + 1;
if (x == INT_MAX)
return INT_MIN;
if (x == INT_MIN)
return x + 1;
if (x >= split)
return x + 1 - INT_MIN;
if (x >= 0)
return INT_MAX - x;
if (x >= negativeSplit)
return INT_MIN - x + 1;
return split -(negativeSplit - x);
}
基本上需要将每个-x=>x=>-x循环与y=>-y=>y循环配对。所以我把裂口的两边配对。
例如,对于4位整数:
0 => 7 => -8 => -7 => 0
1 => 6 => -1 => -6 => 1
2 => 5 => -2 => -5 => 2
3 => 4 => -3 => -4 => 3
x86 asm(AT&T风格):
; input %edi
; output %eax
; clobbered regs: %ecx, %edx
f:
testl %edi, %edi
je .zero
movl %edi, %eax
movl $1, %ecx
movl %edi, %edx
andl $1, %eax
addl %eax, %eax
subl %eax, %ecx
xorl %eax, %eax
testl %edi, %edi
setg %al
shrl $31, %edx
subl %edx, %eax
imull %ecx, %eax
subl %eax, %edi
movl %edi, %eax
imull %ecx, %eax
.zero:
xorl %eax, %eax
ret
代码已检查,所有可能的32位整数都已通过,错误为-2147483647(下溢)。
另一种方法是将状态保持在一位,并在负数的情况下翻转它,注意二进制表示。。。限制为2^29
整数ffn(整数n){
n = n ^ (1 << 30); //flip the bit
if (n>0)// if negative then there's a two's complement
{
if (n & (1<<30))
{
return n;
}
else
{
return -n;
}
}
else
{
if (n & (1<<30))
{
return -n;
}
else
{
return n;
}
}
}
事实上,这些问题更多的是关于面试官与规范、设计、错误处理、边界案例以及为解决方案选择合适的环境等进行斗争,而不是关于实际解决方案。然而::)
这里的函数是围绕封闭的4循环思想编写的。如果函数f只允许落在有符号的32位整数上,那么上面的各种解决方案都将起作用,除了其他人指出的三个输入范围数。minint永远不会满足函数方程,因此如果这是一个输入,我们将引发一个异常。
在这里,我允许Python函数操作并返回元组或整数。任务规范承认这一点,它只指定函数的两个应用程序应该返回一个与原始对象相等的对象,如果它是int32。(我会询问有关规范的更多细节)
这使得我的轨道可以很好且对称,并且可以覆盖所有输入整数(minint除外)。我最初设想的循环是访问半整数值,但我不想陷入舍入错误。因此是元组表示。这是一种将复杂旋转作为元组隐藏的方式,而不使用复杂的算术机制。
注意,在调用之间不需要保留任何状态,但调用者确实需要允许返回值为元组或int。
def f(x) :
if isinstance(x, tuple) :
# return a number.
if x[0] != 0 :
raise ValueError # make sure the tuple is well formed.
else :
return ( -x[1] )
elif isinstance(x, int ) :
if x == int(-2**31 ):
# This value won't satisfy the functional relation in
# signed 2s complement 32 bit integers.
raise ValueError
else :
# send this integer to a tuple (representing ix)
return( (0,x) )
else :
# not an int or a tuple
raise TypeError
因此,将f应用于37两次得到-37,反之亦然:
>>> x = 37
>>> x = f(x)
>>> x
(0, 37)
>>> x = f(x)
>>> x
-37
>>> x = f(x)
>>> x
(0, -37)
>>> x = f(x)
>>> x
37
将f两次应用于零得到零:
>>> x=0
>>> x = f(x)
>>> x
(0, 0)
>>> x = f(x)
>>> x
0
我们处理一个问题没有解决方案的情况(在int32中):
>>> x = int( -2**31 )
>>> x = f(x)
Traceback (most recent call last):
File "<pyshell#110>", line 1, in <module>
x = f(x)
File "<pyshell#33>", line 13, in f
raise ValueError
ValueError
如果你认为函数通过模拟乘以i的90度旋转打破了“无复杂算术”规则,我们可以通过扭曲旋转来改变这一点。这里元组表示半整数,而不是复数。如果你在数字线上追踪轨道,你会得到满足给定函数关系的非相交循环。
f2: n -> (2 abs(n) +1, 2 sign( n) ) if n is int32, and not minint.
f2: (x, y) -> sign(y) * (x-1) /2 (provided y is \pm 2 and x is not more than 2maxint+1
练习:通过修改f来实现这个f2。还有其他解决方案,例如,中间着落点是有理数而不是半整数。有一个分数模块可能很有用。你需要一个符号函数。
这个练习让我真正体会到了动态类型语言的乐趣。我在C中看不到这样的解决方案。
MIN_INT不会失败:
int f(n) { return n < 0 ? -abs(n + 1) : -(abs(n) + 1); }