From 4b129b506fec15d4adbf2258a6816f3b1ae85ce3 Mon Sep 17 00:00:00 2001 From: akmhmgc Date: Sat, 11 Oct 2025 17:42:44 +0900 Subject: [PATCH] 8 --- 8/step1.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 8/step2.md | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 8/step3.md | 34 +++++++++++++++++++++++++++++++++ 8/step4.md | 1 + 4 files changed, 146 insertions(+) create mode 100644 8/step1.md create mode 100644 8/step2.md create mode 100644 8/step3.md create mode 100644 8/step4.md diff --git a/8/step1.md b/8/step1.md new file mode 100644 index 0000000..0c028ba --- /dev/null +++ b/8/step1.md @@ -0,0 +1,56 @@ +# step1 何も見ずに解く + +正規表現で数値に対応する部分を取ってきてintegerに変換する方法を考えた。 +Rubyでは64-bit以上の数値も扱うことができるのでstring to intに変換した時にoverflowのエラーが起きることはないが、 +他の言語だとoverflolwエラーを捕捉して最大値、最小値に変換するのが良いのだろうか。 +ただ、例外処理はスタックトレースの生成などオーバヘッドが大きいので桁数が一定以上を超えた場合は上限、下限の値を早期に返す、という工夫をした方が良さそう。 + +時間計算量はO(N) +空間計算量はO(N) +Nの最大値は200なので1秒以内に間に合う + +```ruby +# @param {String} str +# @return {Integer} +def my_atoi(str) + numeric_string = str.match(/^\s*(\+|-)?([0-9]+)/) + return 0 if numeric_string.nil? + + sign_string = numeric_string.captures[0] || "+" + value_string = numeric_string.captures[1] || "0" + + number_of_digits = 0 + value_string.size.times do |i| + next if value_string[i] == "0" + + number_of_digits = value_string.size - i + break + end + + if number_of_digits > 10 + if sign_string == "+" + return 2 ** 31 - 1 + else + return (-1) * 2 ** 31 + end + end + + if sign_string == "+" + return [2 ** 31 - 1, value_string.to_i].min + else + return [(-1) * 2 ** 31, - value_string.to_i].max + end +end +``` + +解き終わった後にRubyのメソッドを調べたところ、String#[]でキャプチャできることを知った。 +また、`Comparable#clamp`という範囲内の値を返すメソッドがあったので以下のように書ける。 + +```ruby +# @param {String} str +# @return {Integer} +def my_atoi(str) + num = str.lstrip[/^[\+\-]?\d+/].to_i + num.clamp(-2**31, 2**31 - 1) +end +``` diff --git a/8/step2.md b/8/step2.md new file mode 100644 index 0000000..d962174 --- /dev/null +++ b/8/step2.md @@ -0,0 +1,55 @@ +# step2 他の方の解答を見る +- https://github.com/katsukii/leetcode/pull/9 + +例外で処理しなくても確かにこの書き方で対応できる。 + +```java + while (index < length && Character.isDigit(s.charAt(index))) { + int digit = s.charAt(index) - '0'; + + // Check for overflow before adding the digit + if (result > (Integer.MAX_VALUE - digit) / 10) { + return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE; + } + result = result * 10 + digit; + index++; + } +``` + +```ruby +# @param {String} str +# @return {Integer} +def my_atoi(str) + index = 0 + + # skip white space + str = str.lstrip + + # check sign + sign = 1 + if str.start_with?("-") + sign = -1 + index += 1 + end + if str.start_with?("+") + index += 1 + end + + # build result + max_value = 2 ** 31 - 1 + min_value = (-1) * 2 ** 31 + result = 0 + is_integer = ->(string) { string.bytes.first.between?("0".bytes.first, "9".bytes.first )} + while index < str.size && is_integer.call(str[index]) + digit = str[index].to_i + + if result > (max_value - digit) / 10 + return sign == 1 ? max_value : min_value + end + + result = result * 10 + digit + index += 1 + end + result * sign +end +``` diff --git a/8/step3.md b/8/step3.md new file mode 100644 index 0000000..071e8cf --- /dev/null +++ b/8/step3.md @@ -0,0 +1,34 @@ +# step3 3回続けて10分以内に書いてエラーを出さなければOKとする + +```ruby +# @param {String} str +# @return {Integer} +def my_atoi(str) + str_without_left_space = str.lstrip + + index = 0 + sign = 1 + if str_without_left_space.start_with?("-") + sign = -1 + index += 1 + end + if str_without_left_space.start_with?("+") + index += 1 + end + + max_value = 2 ** 31 - 1 + min_value = (-1) * 2 ** 31 + result = 0 + while index < str_without_left_space.size && str_without_left_space[index].between?("0", "9") + digit = str_without_left_space[index].to_i + + if result > (max_value - digit) / 10 + return sign == 1 ? max_value : min_value + end + + result = result * 10 + digit + index += 1 + end + result * sign +end +``` diff --git a/8/step4.md b/8/step4.md new file mode 100644 index 0000000..5941ee1 --- /dev/null +++ b/8/step4.md @@ -0,0 +1 @@ +## step4 レビューを受けて解答を修正