DEV Community

Cover image for LeetCode WalkThru: 'Reverse Integer'
Adriana DiPietro
Adriana DiPietro

Posted on • Edited on

LeetCode WalkThru: 'Reverse Integer'

Hi programmers! Today we will be walking through how to solve LeetCode's Reverse Integer challenge. Click here to pull up the challenge on your end.

After going over the instructions and the examples provided by LeetCode, we will go through two (2) different methods to come to a solution, including a brute force attempt and a optimized attempt.

It is important to see how a single challenge can be solved in multiple ways to understand how different methodologies achieve efficiency, speed and optimization.


Itinerary

1. Instructions + Examples
2. Brute Force Solution
3. Optimized Solution
4. Summary + Recap


Instructions + Examples

Given an integer 'x', return 'x' with 
its digits reversed. If reversing x causes 
the value to go outside the signed 32-bit 
integer range [2^31], then return 0.
Enter fullscreen mode Exit fullscreen mode

In my opinion, LeetCode does not do a great job with these instructions. (Ahem, super vague!) So, in addition to returning the reversed version of the given integer, we have to consider a few more things.

Let's look at the examples to examine what else we should consider when solving this challenge:

Example 1:

Input: x = 123
Output: 321
Enter fullscreen mode Exit fullscreen mode

Example 1 is pretty straight forward. We see that the output is the reversed integer of the input. Simple enough.

Example 2: 

Input: x = -123
Output: -321
Enter fullscreen mode Exit fullscreen mode

Now, Example 2 introduces the possible hiccup (or edge case) of negative integers. We need to consider that the reversal of the integer results in the appropriate placing of the - sign.

Example 3:

Input: x = 120
Output: 21
Enter fullscreen mode Exit fullscreen mode

In Example 3, the 0 is completely popped off from the output. While the presence of the zero does not affect the actual value of the output, semantically we do not present numbers usually with a zero at the beginning. So, we need to also consider removing the zero when necessary.

After looking at both the instructions and the examples, we get a pretty good idea of what we need to accomplish:

1. Reverse the integer and return it.
2. Maintain the positive or negative value of the integer.
3. Remove any zeroes at the beginning of the reversed integer.
4. Return 0 if the given input is larger than 2^31. (If the number is too large, just return 0!)

Let's get started.


Brute Force Attempt

Thanks to JavaScript's built-in methods, the easiest way to reverse data is to use the reverse() method. However, the reverse() method is dedicated only to arrays. So in order to use reverse() let's convert our integer 'x' to an array:

function reverseInt(x){
    // 1. Convert integer to string.
        const intToString = x.toString()

    // 2. Convert string to array.
        const stringToArray = intToString.split('')

        return stringToArray
}

reverseInt(123)

Enter fullscreen mode Exit fullscreen mode

In the above snippet, I broke down the conversion of 'x' from an integer to a string to an array.

  • toString() converts a data value to a string.
  • split() converts a data value to an array.

split() takes an optional parameter called a separator. The separator sits between each array item separating the array item from both its preceding item and succeeding item. In this code challenge, we need the separator.

If we run the above code snippet in our console or sandbox, our output should look like this:

['1', '2', '3']

Now, we have a nice array with each digit of our integer as its own array item. Cool.

Let's keep moving and reverse the array using the reverse() method:

function reverseInt(x){
    // 1. Convert integer to string.
        const intToString = x.toString()

    // 2. Convert string to array.
        const stringToArray = intToString.split('')

   // 3. Reverse array using .reverse().
        const reversedArray = stringToArray.reverse()


        return reversedArray
}

reverseInt(123)
// output => ['3', '2', '1']
Enter fullscreen mode Exit fullscreen mode

Our output would now be ['3', '2', '1'].

With an integer like 123, without a negative sign or any zeroes in the beginning of the array, we could now potentially convert the array back to an integer and we would have the solution.

However, we need to consider those edge cases we saw in the examples provided by LeetCode because in reality integers include negative numbers and zeroes.

First, let's consider if the integer ends with a 0. When we reverse the array the 0 would then be in the first position of the array. For example:

reverseInt(120)
// output => 021
Enter fullscreen mode Exit fullscreen mode

We can use shift() to remove the first element.

function reverseInt(x){
    // 1. Convert integer to string.
        const intToString = x.toString()

    // 2. Convert string to array.
        const stringToArray = intToString.split('')

   // 3. Reverse array using .reverse().
        const reversedArray = stringToArray.reverse()

   // 4. If 0 is in the first position of the array, use shift() to remove it.
      if (reversedArray[0] === '0'){
        reversedArray.shift()
      }
      // ['0', '3', '2', '1'] => ['3', '2', '1']
      // ['0', '0', '3', '2', '1'] => ['3', '2', '1']
}

reverseInt(1230)
reverseInt(12300)

Enter fullscreen mode Exit fullscreen mode

Simple enough, right? Our next edge case we have to consider is the positive or negative value of the integer we pass to our function.

We want to maintain this value, but when we reverse our array the negative sign will end up in the last position or index which semantically does not work.

According to our current code, this would be the output:

reverseInt(-123) // => 321-
Enter fullscreen mode Exit fullscreen mode

But, we want this:

reverseInt(-123) // => -321
Enter fullscreen mode Exit fullscreen mode

Just like reverse(), JavaScript has great built-in functionality to compensate for this edge case. Math.sign() returns either a positive or negative value based on the sign(+/-) of the number passed into it.

Here are some examples:

console.log(Math.sign(123));
// output => 1

console.log(Math.sign(-321));
// output => -1

console.log(Math.sign(0));
// output => 0

console.log(Math.sign('-321'));
// output => -1

Enter fullscreen mode Exit fullscreen mode

Math.sign() will return either -1, 0 or 1. So, how can we apply this to our code to return the reversed integer? We can multiply our reversed integer by Math.sign() passing in our original integer.

First, let's convert our reversed array back to an integer:

function reverseInt(x){
    // 1. Convert integer to string.
        const intToString = x.toString()

    // 2. Convert string to array.
        const stringToArray = intToString.split('')

   // 3. Reverse array using .reverse().
        const reversedArray = stringToArray.reverse()

   // 4. If 0 is in the first position of the array, use shift() to remove it.
      if (reversedArray[0] === '0'){
        reversedArray.shift()
      }
      // ['0', '3', '2', '1'] => ['3', '2', '1']

   // 5. Convert array back into string.
       const backToString = reversedArray.join('')
       console.log(typeof backToString)

   // 6. Convert string back into integer.
       const backToInteger = parseInt(backToString)
       console.log(typeof backToInteger)
}

reverseInt(-123)
// output => 321-

Enter fullscreen mode Exit fullscreen mode

** I use 'typeof' to check the data type of a given variable. It is a great tool to get in the habit of using! **

Now we can apply Math.sign():

function reverseInt(x){
    // 1. Convert integer to string.
        const intToString = x.toString()

    // 2. Convert string to array.
        const stringToArray = intToString.split('')

   // 3. Reverse array using .reverse().
        const reversedArray = stringToArray.reverse()

   // 4. If 0 is in the first position of the array, use shift() to remove it.
      if (reversedArray[0] === '0'){
        reversedArray.shift()
      }
      // ['0', '3', '2', '1'] => ['3', '2', '1']

   // 5. Convert array back into string.
       const backToString = reversedArray.join('')

   // 6. Convert string back into integer and check to see if the integer is larger than 2^31.
       const backToInteger = parseInt(backToString)
       if (backToInteger > 2**31) {
           return 0
       }

   // 7. Using Math.sign(), multiply the value of the original integer by our reversed integer.
     return backToInteger * Math.sign(x)
}

reverseInt(-123)
// output => -321
Enter fullscreen mode Exit fullscreen mode

Paste all this code into your console or sandbox. Our output should be -321! Yes, it worked!

Try it with a few different integers as well:

  • Input: 0
  • Input: 1400
  • Input: -50000
  • Input: 200000000000
  • Input: -0

Optimized Solution

In our brute force attempt, we have a completely valid solution. However, it is messy because it is not DRY. We repeat ourselves quite a bit and overuse variable declarations. Let's optimize our code and reduce it from 15+ lines of code down to a few.

First, we can convert our original integer to a string, then to an array, reverse it, back to a string and then finally back into an integer in one line:

function optimizedReverse(x){
    const reversed = parseInt(x.toString().split('').reverse().join(''))

    return reversed
}

optimizedReverse(345)
// output => 543 
Enter fullscreen mode Exit fullscreen mode

That cleans up a lot of code! Down to two lines already!

Now, we can borrow some code from our brute force attempt to correctly apply the positive or negative value to our reversed integer as well as check to see if the reversed value is greater than 2^31:

function optimizedReverse(x){
    const reversed = parseInt(x.toString().split('').reverse().join(''))
   if (reverse > 2**31) {
       return 0
   }
   return reversed * Math.sign(x)
}

optimizedReverse(-345)
// output => -543 
Enter fullscreen mode Exit fullscreen mode

Done.

We achieved a more optimized solution. With less variable declarations, we save memory during compilation of the code because in JavaScript each variable receives its own space in memory. So, less variables means more free space in memory.

We also save time because the JavaScript engine only has to compile over a few lines of code instead of 15+. This is major in the grand scheme of things. If we can save a few lines of code in each file of a project, we ultimately save a whole lot of time and memory. We want to be efficient and optimized everywhere possible.


Summary + Recap

Thank you for coding along with me. Before you leave let's look back on what this challenge signified:

  • Use console.log() often in your code to check the value of things.
  • Use 'typeof' before a variable to figure out what data type you are working with.
  • Clean up your code where you can.
  • Too many variable declarations => slower code.
  • Too many variable declarations => more memory space is being used up.
  • JavaScript has a plethora of great built-in methods: use them!
  • Optimized means your code uses up less space in memory and takes less time to run.

Remember: code in the way that is best for you. If the optimized solution is confusing and not clear, then don't use it. Keep practicing coding by breaking down your code like we did in the brute force attempt. As you learn, the optimized solution will begin to make sense. Take your time.


Have any questions? Comments? Or suggestions? Leave a comment below :) Feel free to follow me + connect with me on LinkedIn.

Top comments (0)