我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
当前回答
利用JavaScript异常。
function f(n) {
try {
return n();
}
catch(e) {
return function() { return -n; };
}
}
f(f(0))=>0f(f(1))=>-1
其他回答
这是一个C/C++解决方案,它不使用任何按位运算符,也不需要任何数学库,尽管这有点作弊。。。
double f(double n)
{
if (n == (double)(int)n)
return n + 0.5;
else
return -(n - 0.5);
}
这适用于所有32位整数,只有一个异常0x80000000(因为它的相反值不能存储在32位整数系统中)。f(f(n))==-n将始终为真,除非在这种情况下。
不过,我相信有一种更简单、更快的方法来实现它。这只是我第一个想到的。
创建许多解的一种方法是注意,如果我们将整数划分为两个集合S和R
那么我们可以如下创建f:
如果x在R中,则f(x)=g(x)
如果x在S中,则f(x)=-invg(x)
其中invg(g(x))=x,所以invg是g的逆函数。
上面提到的第一个解决方案是分区R=偶数,R=奇数,g(x)=x+1。
我们可以取任意两个无限集合T,P s.T T+U=整数集合,取s=T+(-T),R=U+(-U)。
然后-S=S和-R=R通过它们的定义,我们可以将g取为从S到R的任何1-1对应关系,这必须存在,因为这两个集合都是无限的和可数的。
因此,这将为我们提供许多解决方案,但并非所有解决方案都可以编程,因为它们不会被有限地定义。
例如:
R=可被3整除的数字,S=不可被3除的数字。
然后我们取g(6r)=3r+1,g(6r+3)=3r+2。
f(n) { return -1 * abs(n) }
如何处理溢出问题?还是我错过了重点?
一个C++版本,可能会稍微改变规则,但适用于所有数值类型(浮点、整型、双精度),甚至是重载一元负号的类类型:
template <class T>
struct f_result
{
T value;
};
template <class T>
f_result <T> f (T n)
{
f_result <T> result = {n};
return result;
}
template <class T>
T f (f_result <T> n)
{
return -n.value;
}
void main (void)
{
int n = 45;
cout << "f(f(" << n << ")) = " << f(f(n)) << endl;
float p = 3.14f;
cout << "f(f(" << p << ")) = " << f(f(p)) << endl;
}
或者,您可以滥用预处理器:
#define f(n) (f##n)
#define ff(n) -n
int main()
{
int n = -42;
cout << "f(f(" << n << ")) = " << f(f(n)) << endl;
}