オットセイの経営日誌

データサイエンス系ベンチャーを経営してます。経営のこと、趣味のことつぶやきます。

LeetCode / Reverse Integer

この問題はBad評価も多いですが、公式のSolutionと異なる解法が色々Discussionされているという意味で、面白いです。

https://leetcode.com/problems/reverse-integer/

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.

最後のNoteの内容が重要で、32bitで割り当てられる数の範囲しか扱えない、となっており、それを超えたら0を返す必要があります。

回答・解説

解法1

素朴な解法は、32bitの範囲に注意しつつ、input xをstring型にしてひっくり返し、最後にintegerに戻すというやり方です。

class Solution:
    def reverse(self, x: int) -> int:
        if x >= 2**31-1 or x <= -2**31: 
            return 0
        else:
            s = str(x)
            if x >= 0:
                rev = s[::-1]
            else:
                tmp = s[1:]
                rev = "-" + tmp[::-1] 
            if int(rev) >= 2**31-1 or int(rev) <= -2**31: 
                return 0
            else: 
                return int(rev)

問題文をしっかり読んでいれば解ける問題ですね。(小学校の先生みたいなこと言ってしまった)

解法2

さらにコードを短くするためには、32bitの範囲に入るかの判定を2度行なったところを、絶対値に対して判定することで1度にできないか、と考えます。
input xが正なら1、負なら-1をとる変数sを作成、xとsを掛け、値を正にします。
この値を先ほどと同様string型にしてからひっくり返し、かつ32bitの範囲に入るかの判定も行なってから、再度sをかけて正負を元に戻します。

class Solution:    
    def reverse(self, x: int) -> int:
        s = (x > 0) - (x < 0)
        r = int(str(x*s)[::-1])
        return s*r * (r < 2**31)

個人的には、booleanを使いこなせていないな、、、と自省させられる問いでした。