847 Stimmen

Bestimmung der Funktion f(f(n)) == -n

Eine Frage, die mir bei meinem letzten Vorstellungsgespräch gestellt wurde:

Eine Funktion entwerfen f , so dass:

f(f(n)) == -n

Wo n ist ein 32-Bit vorzeichenbehaftete Ganzzahl Sie können nicht mit komplexen Zahlen arithmetisch rechnen.

Wenn Sie eine solche Funktion nicht für den gesamten Zahlenbereich entwickeln können, entwickeln Sie sie für den größtmöglichen Bereich.

Irgendwelche Ideen?

6 Stimmen

Um welche Stelle ging es bei diesem Vorstellungsgespräch?

9voto

return x ^ ((x%2) ? 1 : -INT_MAX);

9voto

Drew Punkte 14621

:D

boolean inner = true;

int f(int input) {
   if(inner) {
      inner = false;
      return input;
   } else {
      inner = true;
      return -input;
   }
}

5 Stimmen

Vielleicht bekommen Sie auch eine Diskussion darüber, warum globale Variablen schlecht sind, wenn man Sie nicht gleich aus dem Gespräch wirft!

7voto

Yoo Punkte 16264

Als Mathematiker möchte ich meine Sichtweise zu diesem interessanten Problem darlegen. Ich glaube, ich habe die effizienteste Lösung.

Wenn ich mich richtig erinnere, negiert man eine vorzeichenbehaftete 32-Bit-Ganzzahl, indem man einfach das erste Bit umdreht. Zum Beispiel, wenn n = 1001 1101 1110 1011 1110 0000 1110 1010, dann -n = 0001 1101 1110 1011 1110 0000 1110 1010.

Wie definiert man also eine Funktion f, die eine 32-Bit-Ganzzahl mit Vorzeichen annimmt und eine andere 32-Bit-Ganzzahl mit Vorzeichen zurückgibt, mit der Eigenschaft, dass die zweimalige Annahme von f dasselbe ist wie das Umdrehen des ersten Bits?

Lassen Sie mich die Frage neu formulieren, ohne arithmetische Konzepte wie ganze Zahlen zu erwähnen.

Wie definiert man eine Funktion f, die eine Folge von Nullen und Einsen der Länge 32 annimmt und eine Folge von Nullen und Einsen der gleichen Länge zurückgibt, mit der Eigenschaft, dass die zweimalige Ausführung von f dasselbe ist wie das Umdrehen des ersten Bits?

Beobachtung: Wenn Sie die obige Frage für den 32-Bit-Fall beantworten können, dann können Sie sie auch für den 64-Bit-Fall, den 100-Bit-Fall, usw. beantworten. Man wendet f einfach auf die ersten 32 Bit an.

Wenn Sie nun die Frage für den 2-Bit-Fall beantworten können, Voila!

Und ja, es stellt sich heraus, dass es ausreicht, die ersten 2 Bits zu ändern.

Hier ist der Pseudocode

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.

Bemerkung: Der Schritt 2 und der Schritt 3 können zusammen als (a,b) --> (-b, a) zusammengefasst werden. Kommt Ihnen das bekannt vor? Das sollte Sie an die 90-Grad-Drehung der Ebene und die Multiplikation mit der Quadratwurzel von -1 erinnern.

Wenn ich nur den Pseudocode ohne das lange Vorspiel präsentieren würde, würde es wie ein Kaninchen aus dem Hut erscheinen, ich wollte erklären, wie ich zu der Lösung gekommen bin.

6 Stimmen

Ja, das ist ein interessantes Problem. Du kennst dich mit Mathe aus. Aber dies ist ein Problem der Informatik. Du musst also Computer studieren. Die Vorzeichen-Magnituden-Darstellung ist zulässig, aber sie ist vor etwa 60 Jahren aus der Mode gekommen. Die 2er-Komplementierung ist am beliebtesten.

5 Stimmen

Hier ist, was deine Funktion mit den beiden Bits macht, wenn sie zweimal angewendet wird: (a,b) --> (-b, a) --> (-a, -b). Aber wir versuchen, zu (-a, b) zu gelangen, nicht zu (-a, -b).

0 Stimmen

@buti-oxa, Sie haben Recht. Die Zwei-Bit-Operation sollte wie folgt ablaufen: 00 -> 01 -> 10 -> 11 -> 00. Aber dann mein Algorithmus nimmt Vorzeichen-Magnitude-Darstellung, die jetzt unpopulär ist, wie Windows-Programmierer sagte, so denke ich, mein Algorithmus ist von wenig Nutzen.

6voto

Frank Crook Punkte 1456

In PHP

function f($n) {
    if(is_int($n)) {
        return (string)$n;
    }
    else {
        return (int)$n * (-1);
    }
}

Ich bin sicher, Sie können den Sinn dieser Methode für andere Sprachen verstehen. Ich habe explizit zurück auf int gecastet, um es für Leute, die keine schwach typisierten Sprachen verwenden, klarer zu machen. In manchen Sprachen müssen Sie die Funktion überladen.

Das Schöne an dieser Lösung ist, dass sie unabhängig davon funktioniert, ob Sie mit einer Zeichenkette oder einer ganzen Zahl beginnen, und dass sie bei der Rückgabe von f(n) keine sichtbaren Änderungen vornimmt.

Meiner Meinung nach fragt der Interviewer: "Weiß der Bewerber, wie man Daten markiert, um sie später zu bearbeiten?" und "Weiß der Bewerber, wie man Daten markiert, ohne sie zu verändern?" Sie können dies mit Doubles, Zeichenketten oder jedem anderen Datentyp tun, den Sie zuordnen möchten.

0 Stimmen

Aber natürlich ist es eine schreckliche Idee, solche Hacks in echtem Code zu verwenden. Wenn Sie einen Zustand mit Ihren Daten speichern müssen, erstellen Sie einen neuen Typ wie (s, a), und verwenden Sie einen Bindungsoperator, um nur mit dem Ergebnis zu arbeiten. (Dies ist der Zustandsmonade von Haskell sehr ähnlich, aber nicht dasselbe.)

6voto

comonad Punkte 4988

Das ist ganz einfach!

Jede Zahl wird in 4er-Zyklen auf eine andere abgebildet, wenn die erforderliche Bedingung erfüllt ist.

Beispiel:

Die Regeln lauten:

  • 0 0

  • ±2³¹ ±2³¹

  • ungerade gerade, gerade -ungerade:

    forall k, 0 < k < 2³: (2k-1) (2k) (-2k+1) (-2k) (2k-1)

Die einzigen nicht übereinstimmenden Werte sind ±(2³¹-1), da es nur zwei gibt. Es muss zwei geben, die nicht zusammenpassen denn es gibt nur ein Vielfaches von vier der Zahlen in einem Zweierkomplement-System wobei 0 und ±2³¹ bereits reserviert sind.

In einem Einerkomplement-System gibt es +0 und -0. Das war's:

forall k, 0 < k < 2³: (+2k) (+2k+1) (-2k) (-2k-1) (+2k)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X