Problem
The task
is taken from leetcode
Given a 32-bit signed integer, reverse digits of an integer.
Example 1:
Input: 123 Output: 321
Example 2:
Input: -123 Output: -321
Example 3:
Input: 120 Output: 21
Note:
Assume we are dealing with an environment which could only store
integers within the 32-bit signed integer range: [−2^31, 2^31 − 1]. For
the purpose of this problem, assume that your function returns 0 when
the reversed integer overflows.
My solution
/**
* @param {number} x
* @return {number}
*/
const reverse = x => {
if (x === undefined || x === null) { return; }
if (x < 10 && x >= 0) { return x; }
const num = [];
const dissectNum = n => {
if (n <= 0) { return; }
const y = n % 10;
num.push(y);
return dissectNum(Math.floor(n / 10));
};
dissectNum(Math.abs(x));
let tmp = 0;
const maxPow = num.length - 1;
for (let i = 0; i < num.length; i++) {
tmp += num[i] * Math.pow(10, maxPow - i);
}
const result = (x < 0 ? -1 : 1 ) * tmp;
return result > Math.pow(-2, 31) && result < (Math.pow(2, 31) - 1)
? result
: 0;
};
Solution
- The question states that the input is a number 32 signed int so checking for
undefined
ornull
is a waste of time.
The solution is a little long. Some of it due to not being familiar with some old school short cuts.
- To get the sign of a number use
Math.sign
-JavaScript numbers are doubles but when you use bitwise operations on them they are converted to 32 bit signed integers. This gives you a very easy way to check if the result has overflowed.
const signedInt = value => (value | 0) === value; // returns true if int32
-
A 32 bit int can store 9 full decimal digits, with an extra digit
1
or2
, and a sign. you dont need to use an array to hold the reversed digits you can store them in the reversed number as you go. -
JavaScript can handle hex
0x10 === 16
, decimal10 === 10
, octal010 === 8
and binary0b10 === 2
(oh and BIG ints10n === 10
) Hex makes realy easy to remember the lowest and highest int for a given size.Not that you need them to solve the problem, just some handy info.
Some common ways of writing min max 32Ints
const MIN = Math.pow(-2, 31), MAX = Math.pow(2, 31) - 1;
// negative
-0x80000000 === MIN; // true
(0x80000000 | 0) === MIN; // true. Coerce from double to int32
1 << 31 === MIN; // true. Shift 1 to the highest (MSB) bit for negative
//positive
0x7FFFFFFF === MAX; // true
~(1 << 31) === MAX; // true Flips bits of min int32
Rewrite
With that info you can rewrite the solution as
function reverseDigits(int) {
var res = 0, val = Math.abs(int);
while (val > 0) {
res = res * 10 + (val % 10);
val = val / 10 | 0;
}
res *= Math.sign(int);
return (res | 0) === res ? res : 0;
}
I’d just use string manipulation on this, with a simple conditional for the edge cases.
var reverse = n => {
const s = parseInt([..."" + n].reverse().join(""));
return s >= 2 ** 31 ? 0 : Math.sign(n) * s;
};
The approach is to stringify the number, arrayify the string, reverse it, re-join the array into a string and finally parse the reversed string to an integer. parseInt
called on a string such as "546-"
will strip the trailing -
. Then, handle overflow and positive/negative conditions and return the result.
In short, avoid overcomplication and take advantage of high-level language features when possible.
Both answers require you to use Math.sign
. To avoid compatibility issues with some browsers, you could add the following script in your solution.
if (Math.sign === undefined) {
Math.sign = function ( x ) {
return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : +x;
};
}