我在上次面试中遇到的一个问题是:

设计函数f,使得:f(f(n))==-n其中n是32位有符号整数;你不能用复数算术。如果你不能为整个数字范围设计这样的函数,那么就尽可能为最大范围设计它。

有什么想法吗?


当前回答

number f( number n)
{
  static count(0);
  if(count > 0) return -n;
  return n;
}

f(n) = n

f(f(n)) = f(n) = -n

其他回答

我认为这些问题的答案最好用图表直观地解释。当我们忽略零时,我们可以将整数分成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。

Python 2.6:

f = lambda n: (n % 2 * n or -n) + (n > 0) - (n < 0)

我意识到这对讨论毫无帮助,但我无法抗拒。

我参加这个聚会迟到了,现在可能是墓地了。但我有两个贡献,灵感来自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

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]仍然没有赋值。

使用循环置换方法来实现这一点。

-b a b-a

a b-a-b

在微不足道的情况下f(0)返回0

对不起,我的电话回答很粗糙,28日后我将发布完整版本(现在正在检查…)简单地说,假设f(n)是一个循环排列,问题是如何构造它。

定义fk=f(f(f)f(…f(n))))(k fs)情况k=20.微不足道的情况f(0)返回01.分组,在情况k=2时,分组:{0} {1,2} {3,4} ... {n,n+1 |(n+1)%2=0}注意:我只使用Z+,因为结构不需要使用负数。2.构造排列:如果n%2=0,那么a=n-1 b=n如果n%2=1,则a=n b=n+1

这将产生相同的排列,因为n和f(n)在同一组中。

注意排列为P返回P(n)

对于k=2t,只做上面相同的事情,只做MOD k。对于k=2t-1,虽然该方法有效,但毫无意义,啊?(f(n)=-n正常)