From b99dd7342e7c8ef206dc02d773e7ceac37ef837c Mon Sep 17 00:00:00 2001 From: myoshizumi Date: Thu, 3 Jul 2025 11:28:53 +0900 Subject: [PATCH] leetcode 8. String to Integer (atoi) --- .../8. String to Integer (atoi)/README.md | 179 ++++++++++++++++++ .../String to Integer (atoi).ts | 70 +++++++ Mathematics/Prefix Sum/atcoder/B06/B06.go | 117 ++++++++++++ Mathematics/Prefix Sum/atcoder/B06/B06.php | 104 ++++++++++ Mathematics/Prefix Sum/atcoder/B06/README.md | 7 +- 5 files changed, 476 insertions(+), 1 deletion(-) create mode 100644 Algorithm/Other/leetcode/atoi/8. String to Integer (atoi)/README.md create mode 100644 Algorithm/Other/leetcode/atoi/8. String to Integer (atoi)/String to Integer (atoi).ts create mode 100644 Mathematics/Prefix Sum/atcoder/B06/B06.go create mode 100644 Mathematics/Prefix Sum/atcoder/B06/B06.php diff --git a/Algorithm/Other/leetcode/atoi/8. String to Integer (atoi)/README.md b/Algorithm/Other/leetcode/atoi/8. String to Integer (atoi)/README.md new file mode 100644 index 00000000..06aa719d --- /dev/null +++ b/Algorithm/Other/leetcode/atoi/8. String to Integer (atoi)/README.md @@ -0,0 +1,179 @@ +TypeScriptでの `myAtoi` 実装における**各処理ステップを図解**付きで詳細に解説します。例として、入力文字列が `" -042abc"` の場合を扱います。 + +--- + +## ✅ ステップ1: 空白のスキップ + +```typescript +while (i < n && s[i] === ' ') { + i++; +} +``` + +### 🔍 処理前 + +``` +s = " -042abc" + ↑ + i=0 +``` + +空白をスキップしていく: + +``` +s = " -042abc" + ↑ + i=3 +``` + +➡ `i = 3` で空白スキップ完了。`s[3] = '-'` + +--- + +## ✅ ステップ2: 符号の確認 + +```typescript +if (i < n && (s[i] === '+' || s[i] === '-')) { + if (s[i] === '-') sign = -1; + i++; +} +``` + +### 🔍 処理前 + +``` +s = " -042abc" + ↑ + i=3, s[i]='-' +``` + +* `'-'` を発見 → `sign = -1` +* `i++` + +### 🔍 処理後 + +``` +s = " -042abc" + ↑ + i=4, s[i]='0' +sign = -1 +``` + +--- + +## ✅ ステップ3: 数字部分の読み取り + +```typescript +while (i < n && s[i] >= '0' && s[i] <= '9') { + const digit = s[i].charCodeAt(0) - '0'.charCodeAt(0); + result = result * 10 + digit; + i++; +} +``` + +### 🧮 処理ステップ(ループ) + +#### 1周目(s\[4] = '0') + +``` +digit = 0 +result = 0 * 10 + 0 = 0 +i → 5 +``` + +#### 2周目(s\[5] = '4') + +``` +digit = 4 +result = 0 * 10 + 4 = 4 +i → 6 +``` + +#### 3周目(s\[6] = '2') + +``` +digit = 2 +result = 4 * 10 + 2 = 42 +i → 7 +``` + +#### 4周目(s\[7] = 'a') + +* `s[7]` は数字でないため **ループ終了** + +### 🔍 終了時 + +``` +result = 42 +sign = -1 +``` + +--- + +## ✅ ステップ4: オーバーフローの処理と返却 + +```typescript +return result * sign; +``` + +``` +result = 42 +sign = -1 +→ return -42 +``` + +--- + +## ✅ 最終結果 + +``` +入力: " -042abc" +出力: -42 +``` + +--- + +## 🧠 全体のフローチャート風まとめ + +``` +入力: " -042abc" + +↓ ステップ1: 空白スキップ + i = 0 → 3 + +↓ ステップ2: 符号チェック + s[3] = '-' → sign = -1, i = 4 + +↓ ステップ3: 数字読み取り + s[4] = '0' → result = 0 + s[5] = '4' → result = 4 + s[6] = '2' → result = 42 + s[7] = 'a' → 終了 + +↓ ステップ4: 結果に符号適用 + -1 × 42 = -42 + +→ ✅ 出力: -42 +``` + +--- + +## ✅ 他の例も図で簡潔に + +### 例1: `"words and 987"` + +``` +s = "words and 987" +s[0] = 'w'(非数字)→ 数字読み取り前に終了 → return 0 +``` + +--- + +### 例2: `"91283472332"`(オーバーフロー) + +``` +result = 91283472332 > INT_MAX +→ return INT_MAX = 2147483647 +``` + +--- diff --git a/Algorithm/Other/leetcode/atoi/8. String to Integer (atoi)/String to Integer (atoi).ts b/Algorithm/Other/leetcode/atoi/8. String to Integer (atoi)/String to Integer (atoi).ts new file mode 100644 index 00000000..1f7f6a9f --- /dev/null +++ b/Algorithm/Other/leetcode/atoi/8. String to Integer (atoi)/String to Integer (atoi).ts @@ -0,0 +1,70 @@ +// 以下は、指定された仕様に従って `myAtoi` 関数を TypeScript で実装したものです。 +function myAtoi(s: string): number { + const INT_MIN = -(2 ** 31); + const INT_MAX = 2 ** 31 - 1; + + let i = 0; + const n = s.length; + + // 1. 空白をスキップ + while (i < n && s[i] === ' ') { + i++; + } + + // 2. 符号の確認 + let sign = 1; + if (i < n && (s[i] === '+' || s[i] === '-')) { + if (s[i] === '-') sign = -1; + i++; + } + + // 3. 数字を読み取る + let result = 0; + while (i < n && s[i] >= '0' && s[i] <= '9') { + const digit = s[i].charCodeAt(0) - '0'.charCodeAt(0); + + // 4. オーバーフロー確認 + if (result > Math.floor(INT_MAX / 10) || + (result === Math.floor(INT_MAX / 10) && digit > INT_MAX % 10)) { + return sign === 1 ? INT_MAX : INT_MIN; + } + + result = result * 10 + digit; + i++; + } + + return result * sign; +} + +// ### ✅ 処理フローの図解説明 + +// #### 例: `" -042"` の場合 + +// | ステップ | 処理 | 状態 | +// | ---- | ------------------------ | ------------------ | +// | 1 | 空白をスキップ (`i=0→3`) | `i=3`, `s[i]='-'` | +// | 2 | `'-'`を見つけた → `sign = -1` | `i=4`, `sign = -1` | +// | 3 | `0` → `4` → `2` と読み取る | `result = 42` | +// | 4 | 範囲内 → そのまま返す | `return -42` | + +// --- + +// ### ✅ 制約への対応 + +// * 空文字列や非数字始まり → `0` を返す +// * 数値部分が 32-bit の範囲外 → オーバーフロー対策済み +// * 入力が `"words and 987"` のようなケース → 先頭が非数字 → `0` を返す + +// --- + +// ### ✅ テスト例 + +// ```typescript +// console.log(myAtoi("42")); // 42 +// console.log(myAtoi(" -042")); // -42 +// console.log(myAtoi("1337c0d3")); // 1337 +// console.log(myAtoi("0-1")); // 0 +// console.log(myAtoi("words and 987")); // 0 +// console.log(myAtoi("-91283472332")); // -2147483648(下限に丸められる) +// console.log(myAtoi("91283472332")); // 2147483647(上限に丸められる) +// ``` diff --git a/Mathematics/Prefix Sum/atcoder/B06/B06.go b/Mathematics/Prefix Sum/atcoder/B06/B06.go new file mode 100644 index 00000000..5117f017 --- /dev/null +++ b/Mathematics/Prefix Sum/atcoder/B06/B06.go @@ -0,0 +1,117 @@ +// ### 🔍 よくあるランタイムエラーの原因(Go) + +// | 原因 | 内容 | +// | ---------------- | ------------------------------------------------------- | +// | ❌ インデックスエラー | `acc[L-1]` のように `L=1` のとき `acc[0]` にアクセスできない or スライス外参照 | +// | ❌ スキャン不足 | 入力のスキャン回数が `Q` に足りていない(クエリが途中で終わる) | +// | ❌ スペースのない入力の処理ミス | `bufio.Scanner` が 1行ずつ読み取る前提で、改行の無い入力に対応できていない | +// | ❌ 空文字列の変換 | `strconv.Atoi("")` のように、空の文字列を数値に変換してエラー | + +// ### ✅ 修正版 Go コード(安全対策込み) + +package main + +import ( + "bufio" + "os" + "strconv" + "strings" +) + +func main() { + reader := bufio.NewReader(os.Stdin) + + // Read N + line, _ := reader.ReadString('\n') + N, _ := strconv.Atoi(strings.TrimSpace(line)) + + // Read A + line, _ = reader.ReadString('\n') + Astr := strings.Fields(line) + A := make([]int, N+1) // 1-indexed + for i := 1; i <= N; i++ { + A[i], _ = strconv.Atoi(Astr[i-1]) + } + + // Build prefix sum + acc := make([]int, N+1) + for i := 1; i <= N; i++ { + acc[i] = acc[i-1] + A[i] + } + + // Read Q + line, _ = reader.ReadString('\n') + Q, _ := strconv.Atoi(strings.TrimSpace(line)) + + writer := bufio.NewWriter(os.Stdout) + defer writer.Flush() + + // Read and process queries + for i := 0; i < Q; i++ { + line, err := reader.ReadString('\n') + if err != nil { + break // 安全策 + } + LR := strings.Fields(line) + if len(LR) < 2 { + continue // 不正入力回避 + } + L, _ := strconv.Atoi(LR[0]) + R, _ := strconv.Atoi(LR[1]) + + if L < 1 || R > N || L > R { + writer.WriteString("draw\n") // 安全なフォールバック + continue + } + + ones := acc[R] - acc[L-1] + total := R - L + 1 + zeros := total - ones + + if ones > zeros { + writer.WriteString("win\n") + } else if zeros > ones { + writer.WriteString("lose\n") + } else { + writer.WriteString("draw\n") + } + } +} + +// ## ✅ 修正ポイントまとめ + +// | 修正箇所 | 説明 | | | +// | --------------------------- | ----------------------- | - | ----------------------- | +// | ✅ `bufio.NewReader` 使用 | `bufio.Scanner` の行制限を回避 | | | +// | ✅ `strings.Fields` 使用 | 空白区切り入力を安全に処理 | | | +// | ✅ `acc` と `A` を 1-indexed に | `acc[L-1]` アクセスを安全にするため | | | +// | ✅ クエリ境界チェック | \`L < 1 | | R > N\` などの入力ミスで落ちないように | + +// --- + +// ## ✅ 確認テスト(例) + +// ### 入力 + +// ``` +// 7 +// 0 1 1 0 1 0 0 +// 3 +// 2 5 +// 2 7 +// 5 7 +// ``` + +// ### 出力 + +// ``` +// win +// draw +// lose +// ``` + +// ## ✅ 補足 + +// * 万が一、`LR` の長さが不足する場合(不完全な入力など)にも対応。 +// * クエリ数が `Q` 未満でもクラッシュしないように `err != nil` チェック。 + diff --git a/Mathematics/Prefix Sum/atcoder/B06/B06.php b/Mathematics/Prefix Sum/atcoder/B06/B06.php new file mode 100644 index 00000000..eeab2acb --- /dev/null +++ b/Mathematics/Prefix Sum/atcoder/B06/B06.php @@ -0,0 +1,104 @@ +