😇

LeetCode 8. String to Integer (atoi) を完全に理解する by TypeScript

2022/07/31に公開

String to Integer (atoi)

問題文

Implement the myAtoi(string s) function, which converts a string to a 32-bit signed integer (similar to C/C++'s atoi function).

The algorithm for myAtoi(string s) is as follows:

Read in and ignore any leading whitespace.
Check if the next character (if not already at the end of the string) is '-' or '+'. Read this character in if it is either. This determines if the final result is negative or positive respectively. Assume the result is positive if neither is present.
Read in next the characters until the next non-digit character or the end of the input is reached. The rest of the string is ignored.
Convert these digits into an integer (i.e. "123" -> 123, "0032" -> 32). If no digits were read, then the integer is 0. Change the sign as necessary (from step 2).
If the integer is out of the 32-bit signed integer range [-231, 231 - 1], then clamp the integer so that it remains in the range. Specifically, integers less than -231 should be clamped to -231, and integers greater than 231 - 1 should be clamped to 231 - 1.
Return the integer as the final result.
Note:

Only the space character ' ' is considered a whitespace character.
Do not ignore any characters other than the leading whitespace or the rest of the string after the digits.

日本語 by DeepL

文字列を32ビット符号付き整数に変換する myAtoi(string s) 関数を実装する(C/C++ の atoi 関数に似ている)。

myAtoi(string s)のアルゴリズムは以下の通りである。

読み込んで,先頭の空白文字は無視する。
次の文字が(まだ文字列の末尾にない場合)'-'または'+'であるかどうかをチェックする。次の文字が'-'か'+'かを調べる。これにより、最終的な結果がそれぞれ負か正かが決定される。どちらも存在しない場合、結果は正であると仮定する。
次の数字でない文字、あるいは入力の終端に達するまで、次の文字を読み込む。文字列の残りは無視される。
これらの数字を整数に変換する (すなわち、"123" -> 123, "0032" -> 32) 。桁が読み取れなかった場合、整数は0である。必要に応じて符号を変更する(ステップ2から)。
整数が32ビット符号付き整数範囲 [-231, 231 - 1] から外れている場合、整数が範囲内に収まるようにクランプする。具体的には、-231より小さい整数は-231に、231 - 1より大きい整数は231 - 1にクランプされなければならない。
最終結果として整数を返す。
注意

空白文字 ' ' だけが空白文字とみなされる。
先頭の空白文字や数字以降の文字列以外の文字は無視してはならない。

www.DeepL.com/Translator(無料版)で翻訳しました。

例題

Input: s = "42"
Output: 42
Explanation: The underlined characters are what is read in, the caret is the current reader position.
Step 1: "42" (no characters read because there is no leading whitespace)
         ^
Step 2: "42" (no characters read because there is neither a '-' nor '+')
         ^
Step 3: "42" ("42" is read in)
           ^
The parsed integer is 42.
Since 42 is in the range [-231, 231 - 1], the final result is 42.

検討

条件がめちゃくちゃ多くて長い。
ちなみにparseIntを使ってしまえば簡単。
最初は自力で実装してなんとかテストを通したけどかなり大変だった。
どちらかというとparseIntを使わずにコツコツ解いたほうが面白いかもしれない。
+と-の扱いとかそのあたりが大変なのだ。

回答

function myAtoi(s: string): number {
  /*
    とりあえず両端の空白を消しておく
    文字列がなくなったら0を返す
  */
  const trimmedS = s.trim();
  if (trimmedS === "") return 0;

  /*
    parseInt使ったら簡単……。
    10進数ということを明示する。
    isNanのときは0を返す
  */
  const parsedInt = parseInt(trimmedS, 10);
  if (isNaN(parsedInt)) return 0;

  /* 
    最小が決まっているので、それより小さいなら最小値を返す
    -2の31乗は-2147483648だけど、powで計算しておく
  */
  const minRange = Math.pow(-2, 31);
  if (parsedInt < minRange) return minRange;

  /* 
    最大が決まっているので、それより大きいなら最大値を返す
    2の31乗-1は2147483647だけど、powで計算しておく
    でもべつに問題文に書かれてるなら定数にしても良い気がする。
    わざわざ計算する必要あるのかな
  */
  const maxRange = Math.pow(2, 31) - 1;
  if (parsedInt > maxRange) return maxRange;

  /* parseIntを使えば簡単 */
  return parsedInt;
}

自力実装すると条件多くて大変。
上の回答だとあんまり解いた感ないかも。

  1. 両端の空白を消す
  2. 空白消してなくなったら0
  3. 10進数でパースする
  4. おかしな数字だったら0
  5. 最小値超えてたら最小値にする
  6. 最大値超えてたら最大値にする
  7. 終わり

Discussion