Go to “Reverse Integer (#7)” on Leetcode ↗

Ruby’s integers aren’t limited to 32-bits, so we don’t have to worry about overflows. However, if the problem insists that 0 must be returned if the number would overflow, we can then check if the reversed number would be greater than the largest 32-bit integer value, and return 0 if that’s the case. Most interviewers would probably be ok if you didn’t bothered with this bit, since it’s not the interesting part of the problem.

Solution 1: Stringify and Reverse

Most people would consider this cheating, but you could just turn the integer into a string, reverse that string, and turn it back into an integer. The only tricky part is when given a negative — we want to stringify and reverse the absolute value of the number (the positive part of it), and tack on the negative sign if the original number is negative.

INT32_MAX = 2 ** 31 - 1
INT32_MIN = -1 * 2 ** 31

def reverse(x)
  reversed_integer = x.abs.to_s.reverse.to_i
  solution = x < 0 ? -1 * reversed_integer : reversed_integer
  solution > INT32_MAX || solution < INT32_MIN ? 0 : solution
end

Solution 2: Reverse a Digit Array

The modulo operator (%) returns the remainder that would result from a division. We can use a repeated combination of % and / to extract all the digits from a number, one-by-one. If we % and / by 10 each time, we extract digits from right-to-left. We can append these digits to an array, such that the resulting array is in the order we want our solution to be.

Once we have this array, we can use place-value math to recombine them into the final number. For example, if we have the digits [1, 2, 3, 4] in an array, and want to combine them into the number 1234, we’d multiple the 1 by 103, the 2 by 102, the 3 by 101, and the 4 by 100, and add all that together. If n is the number of digits, each digit at index I gets multiplied by 10n - 1 - I.

INT32_MAX = 2 ** 31 - 1
INT32_MIN = -1 * 2 ** 31

def reverse(x)
  x_copy = x.abs
  digits = []
  loop do
    digits << x_copy % 10
    x_copy /= 10
    break if x_copy == 0
  end

  solution = 0
  digits.each_with_index do |digit, index|
    place_value = 10 ** (digits.length - 1 - index)
    solution += digit * place_value
  end

  solution = x < 0 ? -1 * solution : solution
  solution > INT32_MAX || solution < INT32_MIN ? 0 : solution
end

Solution 3: Digit By Digit

If we can’t (or don’t want to) allocate an additional array, we can do something similar, but we need to first determine what n would be by running through a / loop first. Then, rather than looping through an array of digits, we use % to extract a digit, and place-value multiplication to put it into the right place in the solution, within each iteration of the main loop.

INT32_MAX = 2 ** 31 - 1
INT32_MIN = -1 * 2 ** 31

def reverse(x)
  x_copy = x.abs
  n = 1
  loop do
    x_copy /= 10
    break if x_copy == 0
    n += 1
  end

  solution = 0
  x_copy = x.abs
  (1..n).each do |i|
    place_value = 10 ** (n - i)
    next_digit = x_copy % 10
    solution += next_digit * place_value
    x_copy /= 10
  end

  solution = x < 0 ? -1 * solution : solution
  solution > INT32_MAX || solution < INT32_MIN ? 0 : solution
end

Runtime: This solution is O(log(x)) because both loops run as many iterations as there are digits in x, and the work within both loops runs in constant time.

Memory: This solution uses a constant amount of memory.