我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
我在上次面试中遇到的一个问题是:
设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。
有什么想法吗?
当前回答
Wolfram语言的解决方案:
f[f[n_]] := -n
应用程序:
In[2]:= f[f[10]]
Out[2]= -10
In[3]:= f[10]
Out[3]= f[10]
因为这个问题没有说明f(n)的值,所以f[n]仍然没有赋值。
其他回答
作为一名数学家,我想分享我对这个有趣问题的看法。我认为我有最有效的解决方案。
如果我没记错的话,只需翻转第一位,就可以将有符号的32位整数取反。例如,如果n=1001 1101 1110 1011 1110 0000 1110 1010,则-n=0001 1101 11101 1011 11100 0000 1110 010。
那么,我们如何定义一个函数f,它接受一个带符号的32位整数,并返回另一个有符号的32位数整数,该函数的属性是:接受两次f与翻转第一位相同?
让我重新表述这个问题,而不提整数之类的算术概念。
我们如何定义一个函数f,它接受长度为32的一系列0和1,并返回长度相同的一系列零和1,同时具有两次接受f与翻转第一位相同的性质?
观察:如果你能回答32位情况的上述问题,那么你也可以回答64位情况、100位情况等。你只需将f应用于前32位。
现在,如果你能回答2位案例的问题,哇!
是的,改变前2位就足够了。
这是伪代码
1. take n, which is a signed 32-bit integer.
2. swap the first bit and the second bit.
3. flip the first bit.
4. return the result.
备注:步骤2和步骤3可以概括为(a,b)-->(-b,a)。看起来很眼熟?这应该会让你想起平面的90度旋转以及乘以-1的平方根。
如果我只是单独展示了伪代码,而没有冗长的前奏,那么它看起来就像脱口而出的兔子,我想解释一下我是如何得到解决方案的。
另一种方法是将状态保持在一位,并在负数的情况下翻转它,注意二进制表示。。。限制为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;
}
}
}
C++
struct Value
{
int value;
Value(int v) : value(v) {}
operator int () { return -value; }
};
Value f(Value input)
{
return input;
}
我参加这个聚会迟到了,现在可能是墓地了。但我有两个贡献,灵感来自viraptor先前使用lambda的Python答案。读者可能认为该解决方案仅在非类型化语言中可行,而在类型化语言中将需要一些明确的额外标记。
但下面是Haskell中的解决方案1(我不是Haskell专家)。它有点作弊,因为从技术上讲,两个f是两个不同的实现。(一个f::Int->()->Int,另一个f::(()->Int)->Int)
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies #-}
module Main where
class Tran σ τ | σ -> τ where
tran :: σ -> τ
instance Tran Int (() -> Int) where
tran n = \_ -> (-n)
instance Tran (() -> Int) Int where
tran g = g ()
f :: Tran σ τ => σ -> τ
f = tran
main :: IO ()
main = do
print $ f (f (42 :: Int)) -- --> -42
print $ f (f (0 :: Int)) -- --> 0
print $ f (f (-69 :: Int)) -- --> 69
接下来是Typed Racket中的解决方案2。这一个满足了最大可能域的属性,因为Racket中的Number最多包含复数:
#lang typed/racket
(: f (case->
[Number -> (-> Number)]
[(-> Number) -> Number]))
(define (f x)
(if (number? x) (λ () (- x)) (x)))
(f (f 42)) ; --> -42
(f (f 0)) ; --> 0
(f (f -69)) ; --> 69
(f (f 3/4)) ; --> -3/4
(f (f 8+7i)) ; --> -8-7i
Tcl:
proc f {input} {
if { [string is integer $input] } {
return [list expr [list 0 - $input]]
} else {
return [eval $input]
}
}
% f [f 1]
-1
按照其他一些答案的思路。。。如果它是一个整数,则返回一个返回该数字负数的命令。如果不是数字,请对其求值并返回结果。