LeetCode WalkThru: '역정수'

안녕하세요 프로그래머입니다! 오늘은 LeetCode의 Reverse Integer Challenge를 푸는 방법을 살펴보겠습니다. here을 클릭하여 끝에서 챌린지를 불러옵니다.

LeetCode에서 제공하는 지침과 예제를 살펴본 후 무차별 대입 시도와 최적화된 시도를 포함하여 솔루션에 도달하기 위해 두 가지 다른 방법을 살펴보겠습니다.

다양한 방법론이 효율성, 속도 및 최적화를 달성하는 방법을 이해하려면 단일 문제를 여러 방법으로 해결할 수 있는 방법을 확인하는 것이 중요합니다.


여정



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

지침 + 예

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.

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

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

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

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.


무차별 대입 시도

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)

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']

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

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)

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-

But, we want this:

reverseInt(-123) // => -321

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

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-

** 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

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

최적화된 솔루션

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 

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 

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.


요약 + 요약

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.

좋은 웹페이지 즐겨찾기