Problem

Write a function to swap two number in place without temporary variables.

Examples

Example 1

1
2
3
Input: a = 3, b = 7
Output: a = 7, b = 3
Explanation: Swapping two integer variables without a temporary variable should exchange their values.

Example 2

1
2
3
Input: a = 5, b = 5
Output: a = 5, b = 5
Explanation: Values are equal  swapping without a temporary variable should leave them unchanged.

Solution

Method 1 - The XOR (exclusive) trick

Intuition

XOR is a bitwise operation that acts independently on each bit. Two useful identities are:

  • v ^ v = 0 (a value XOR itself is zero)
  • v ^ 0 = v (a value XOR zero is the value)

When we write a = a ^ b, the result stores, for every bit position, whether a and b differed at that position (1) or not (0). If we then XOR that result back with one of the original values we can recover the other value, because:

  • (a ^ b) ^ b = a (since b ^ b = 0 and x ^ 0 = x)

The three-step XOR swap works by using these identities to interleave and then restore bits:

  1. a = a ^ b — now a holds the bitwise differences (call this D = a^b).
  2. b = b ^ a — since a is D, this becomes b = b ^ D = b ^ (a ^ b) = a (so b becomes the original a).
  3. a = a ^ b — now a = D ^ a(original) which evaluates to b (the original b).

Because each step is bitwise and reversible, the pair (a, b) ends up swapped without allocating an extra variable. The trick only works safely for integer-like types and when you avoid the special cases below.

Approach

  1. If swapping the same memory location (or the same variable) do nothing — swapping in-place is a no-op.
  2. If the two values are equal, do nothing — XORing identical values can produce zero and lead to incorrect results when performed in-place.
  3. Otherwise perform three XOR operations in sequence (use a and b):
  • a ^= b
  • b ^= a
  • a ^= b

Caveats

The XOR swap works for integer-like types but has several practical pitfalls you should guard against. Below are the main issues and short guidance.

Undefined behaviour

The compact one-liner a ^= b ^= a ^= b; is undefined behaviour in C/C++ because it modifies a more than once without intervening sequence points. Always use the explicit three-statement sequence and avoid modifying the same storage twice in a single expression.

Aliasing and equal-values

If the two operands refer to the same memory location (aliasing) or are equal, an unguarded XOR swap can produce zeroed results. Guard with if (&a == &b) return; for pointer/reference cases or if (a == b) return; for value checks.

Floating-point and non-integers

The XOR trick is a bitwise integer operation and is not suitable for floating-point or non-integer types.

Concurrency and atomicity

These swaps are not atomic. In multithreaded code use proper synchronization or hardware-supported atomic-swap operations.

Recommendation

For readable, robust production code prefer a temporary variable unless you have a specific reason to avoid one; use the XOR trick only when you understand and guard for the issues above.

Safe pattern

Prefer a guarded swap to avoid aliasing and equal-value pitfalls:

1
2
3
4
5
6
// C-style guard, works similarly in other languages (use references/pointers where available)
if (&a == &b) return;   // same address — no-op
if (a == b) return;     // equal values — no-op
a ^= b;
b ^= a;
a ^= b;

Bit-level example

Let a = 5 (binary 0101) and b = 3 (binary 0011):

  • D = a ^ b = 0101 ^ 0011 = 0110
  • After a = a ^ ba = 0110 (D)
  • After b = b ^ ab = 0011 ^ 0110 = 0101 (original a)
  • After a = a ^ ba = 0110 ^ 0101 = 0011 (original b)

Final values: a = 3, b = 5.

Complexity

  • Time complexity: O(1) – A constant number of bitwise operations are performed.
  • 🧺 Space complexity: O(1) – No additional storage is used.

Code

1
2
3
4
5
6
7
8
// Pointer-style swap using XOR. Caller passes addresses of integers.
void swapNumbers(int *a, int *b) {
  if (a == b) return; // same address
  if (*a == *b) return; // equal values — XOR would zero
  *a ^= *b;
  *b ^= *a;
  *a ^= *b;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Swap two integers by reference using XOR. Works for integer types.
#include <iostream>

class Solution {
public:
  static void swapNumbers(int &a, int &b) {
    if (&a == &b) return;
    if (a == b) return;
    a ^= b;
    b ^= a;
    a ^= b;
  }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import "fmt"
// swapNumbers swaps two integer values via pointers using XOR.
func swapNumbers(a, b *int) {
    if a == b {
        return
    }
    if *a == *b {
        return
    }
    *a ^= *b
    *b ^= *a
    *a ^= *b
}

func main() {
  a, b := 3, 7
  swapNumbers(&a, &b)
  fmt.Println(a, b) // 7 3
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Demonstration in main since Java primitives are passed by value.
class Solution {
  public static void main(String[] args) {
    int a = 3, b = 7;
    if (a != b) {
      a ^= b;
      b ^= a;
      a ^= b;
    }
    System.out.println(a + " " + b); // 7 3
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Demonstration in main since Kotlin primitives are value types.
fun main() {
  var a = 3
  var b = 7
  if (a != b) {
    a = a xor b
    b = b xor a
    a = a xor b
  }
  println("$a $b") // 7 3
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Demonstration in main since Python integers are immutable and there is
# no pass-by-reference for primitives. Use local variable XOR swap.
def main() -> None:
  a: int = 3
  b: int = 7
  if a != b:
    a ^= b
    b ^= a
    a ^= b
  print(a, b)  # 7 3

if __name__ == "__main__":
    main()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// Swap two integers via mutable references using XOR.
fn swap_numbers(a: &mut i32, b: &mut i32) {
    if (a as *const _) == (b as *const _) { return }
    if *a == *b { return }
    *a ^= *b;
    *b ^= *a;
    *a ^= *b;
}

fn main() {
  let mut a: i32 = 3;
  let mut b: i32 = 7;
  swap_numbers(&mut a, &mut b);
  println!("{} {}", a, b); // 7 3
}
1
2
3
4
5
6
7
8
9
// Demonstration in main since TypeScript numbers are primitives (by value).
let a: number = 3;
let b: number = 7;
if (a !== b) {
  a ^= b;
  b ^= a;
  a ^= b;
}
console.log(a, b); // 7 3

Method 2 - Addition and subtraction trick

Intuition

You can swap two numeric values using arithmetic: add them and then subtract to recover each original value in swapped positions. This uses no extra user-visible temporary variables but is vulnerable to integer overflow for fixed-width types.

Approach

  1. If the two variables refer to the same location (or are the same variable) do nothing — swapping a variable with itself is a no-op.
  2. Perform three arithmetic operations:
    • a = a + b
    • b = a - b (now holds original a)
    • a = a - b (now holds original b)
  3. Use this only when you are certain the addition will not overflow the numeric type. For safety, in production use a temporary variable or a wider type when possible.

Complexity

  • Time complexity: O(1) – Only three arithmetic operations are performed.
  • 🧺 Space complexity: O(1) – No extra storage is used.

Code

1
2
3
4
5
6
7
8
// Pointer-style swap using addition/subtraction. Caller passes addresses.
void swapNumbers(int *a, int *b) {
  if (a == b) return; // same address
  // Be careful: addition may overflow for fixed-width ints.
  *a = *a + *b;
  *b = *a - *b; // original *a
  *a = *a - *b; // original *b
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Swap two integers by reference using addition/subtraction.
#include <iostream>

class Solution {
public:
  static void swapNumbers(int &a, int &b) {
    if (&a == &b) return;
    // Beware of overflow for fixed-width ints
    a = a + b;
    b = a - b; // original a
    a = a - b; // original b
  }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import "fmt"

// swapNumbers swaps two integer values via pointers using addition/subtraction.
func swapNumbers(a, b *int) {
  if a == b { return }
  *a = *a + *b
  *b = *a - *b
  *a = *a - *b
}

func main() {
  a, b := 3, 7
  swapNumbers(&a, &b)
  fmt.Println(a, b) // 7 3
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Demonstration in main since Java primitives are passed by value.
class Solution {
  public static void main(String[] args) {
  int a = 3, b = 7;
  // Beware of overflow for 32-bit ints in other inputs
  a = a + b;
  b = a - b; // original a
  a = a - b; // original b
  System.out.println(a + " " + b); // 7 3
  }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// Demonstration in main since Kotlin primitives are value types.
func main() {
  a, b := 3, 7
  swapNumbers(&a, &b)
  fmt.Println(a, b) // 7 3
}
  y = x - y // original x
  x = x - y // original y
  println("$x $y") // 7 3
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Demonstration in main for Python; Python ints are unbounded so overflow is not a concern here.
def main() -> None:
  a: int = 3
  b: int = 7
  a = a + b
  b = a - b
  a = a - b
  print(a, b)  # 7 3

if __name__ == "__main__":
  main()
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// Swap two integers via mutable references using addition/subtraction.
fn swap_numbers(a: &mut i64, b: &mut i64) {
  if (a as *const _) == (b as *const _) { return }
  *a = *a + *b;
  *b = *a - *b;
  *a = *a - *b;
}

fn main() {
  let mut a: i64 = 3;
  let mut b: i64 = 7;
  swap_numbers(&mut a, &mut b);
  println!("{} {}", a, b); // 7 3
}
1
2
3
4
5
6
7
8
// Demonstration in main since TypeScript numbers are primitives (by value).
let a: number = 3;
let b: number = 7;
// Note: JS numbers are floating point; use with care for large integers.
a = a + b;
b = a - b; // original a
a = a - b; // original b
console.log(a, b); // 7 3