Skip to content

Commit dd18518

Browse files
committed
leetcode 9. Palindrome Number
1 parent 4905fe6 commit dd18518

3 files changed

Lines changed: 265 additions & 0 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# 承知しました。以下は、LeetCode形式に完全準拠した **Python(3.11.4)による「回文判定」関数の実装**です。
2+
# 文字列変換を使わず、処理時間・メモリ使用量にも配慮した解法です。
3+
4+
# ## ✅ 問題文要約
5+
6+
# > 整数 `x` が与えられたとき、それが回文であるなら `True` を、そうでなければ `False` を返してください。
7+
# > **ただし、文字列変換を使わない実装が推奨されます。**
8+
9+
# ## ✅ 実装:LeetCode形式(Python + 型ヒント + 最適化)
10+
11+
class Solution:
12+
def isPalindrome(self, x: int) -> bool:
13+
# 負数や末尾0(0を除く)は回文にはなり得ない
14+
if x < 0 or (x % 10 == 0 and x != 0):
15+
return False
16+
17+
reverted: int = 0
18+
while x > reverted:
19+
reverted = reverted * 10 + x % 10
20+
x //= 10
21+
22+
# 偶数桁: x == reverted、奇数桁: x == reverted // 10
23+
return x == reverted or x == reverted // 10
24+
25+
# ## ✅ 処理の説明(Follow-up 条件満たす)
26+
27+
# | ステップ | 説明 |
28+
# | ------ | ----------------------------------------------------- |
29+
# | 入力前処理 | 負数または末尾が0の数値(0は除く)は絶対に回文にならない |
30+
# | 数値反転処理 | `x` の後半部分だけを `reverted` に反転しながら保持 |
31+
# | 判定 | `x == reverted` または `x == reverted // 10` で中央の桁を除いた比較 |
32+
33+
34+
# ## ✅ 時間計算量・メモリ使用量
35+
36+
# | 項目 | 内容 |
37+
# | ---------- | ---------------------------------------- |
38+
# | **時間計算量** | O(log₁₀x) → 桁数分だけループ(最大で10回程度) |
39+
# | **空間計算量** | O(1) → 変数 `x`, `reverted` の2つ(定数個)しか使わない |
40+
# | **使用メモリ例** | 約 16〜24 bytes(整数2個、内部処理含む) |
41+
42+
43+
# ## ✅ 動作例(内部での動き)
44+
45+
# 例: `x = 1221`
46+
47+
# | 反転途中 | x | reverted |
48+
# | ---- | -------------------- | -------- |
49+
# | 1回目 | 122 | 1 |
50+
# | 2回目 | 12 | 12 |
51+
# | 判定 | 12 == 12 → True(偶数桁) | |
52+
53+
54+
# ## ✅ メリットと特徴
55+
56+
# * 🚫 `str()`や`[::-1]`などの文字列操作を一切使わない
57+
# * 🚀 速度も空間効率も非常に良い
58+
# * 💯 LeetCodeの「Follow up」条件も完全クリア
59+
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// 以下は、TypeScript を用いて **整数が回文かどうかを判定する**プログラムです。
2+
// `fs` を使って標準入力から値を読み取り、**整数変換なし**(文字列に変換しない)で回文を判定します。
3+
4+
// ---
5+
6+
// ### ✅ 要件まとめ
7+
8+
// * `fs` 使用による標準入力対応。
9+
// * `x` を文字列に変換せずに回文か判定。
10+
// * 計算量とメモリ量を抑えた実装。
11+
12+
// ---
13+
14+
// ### ✅ TypeScript 実装(`fs` 使用・整数のみ)
15+
16+
// palindrome.ts
17+
import * as fs from 'fs';
18+
19+
function isPalindrome(x: number): boolean {
20+
// 負の数や10の倍数(ただし0は除く)は回文にならない
21+
if (x < 0 || (x % 10 === 0 && x !== 0)) return false;
22+
23+
let reverted = 0;
24+
let original = x;
25+
26+
// 半分だけ反転させる
27+
while (x > reverted) {
28+
reverted = reverted * 10 + x % 10;
29+
x = Math.floor(x / 10);
30+
}
31+
32+
// xが奇数桁の時はreverted/10で中央の数字を削除
33+
return x === reverted || x === Math.floor(reverted / 10);
34+
}
35+
36+
// 標準入力から読み込む
37+
const input = fs.readFileSync('/dev/stdin', 'utf-8').trim();
38+
const x = parseInt(input);
39+
40+
console.time('exec');
41+
const result = isPalindrome(x);
42+
console.timeEnd('exec');
43+
44+
console.log(result);
45+
// ### ✅ 使用方法(例)
46+
47+
// 以下のように、値を標準入力に渡して実行します:
48+
49+
// ```bash
50+
// echo 121 | ts-node palindrome.ts
51+
// # 出力: true
52+
// ```
53+
54+
// ```bash
55+
// echo -121 | ts-node palindrome.ts
56+
// # 出力: false
57+
// ```
58+
59+
// ```bash
60+
// echo 10 | ts-node palindrome.ts
61+
// # 出力: false
62+
// ```
63+
64+
// ---
65+
66+
// ### ✅ 計算量・メモリ使用量
67+
68+
// * 時間計算量:O(log₁₀(x))(最大で10桁程度)
69+
// * 空間計算量:O(1)(定数変数のみ使用)
70+
71+
// ---
72+
73+
// ### ✅ 解法ポイント(Follow up 対応)
74+
75+
// * **文字列変換を避ける**ため、整数の下位桁から数を逆に構築。
76+
// * 逆数が元の数と一致すれば回文。
77+
// * 途中で反転数が元の数を超えたら、中央を跨いだので比較可能。
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
TypeScriptでの「整数が回文かどうか判定する処理」について、**各ステップを図解付きで具体的に解説**します。
2+
今回は文字列変換をせず、整数のまま判定するアルゴリズムに基づきます。
3+
4+
---
5+
6+
## 🔢 処理の流れ
7+
8+
### Step 1: 入力の前処理(負数や10の倍数チェック)
9+
10+
```ts
11+
if (x < 0 || (x % 10 === 0 && x !== 0)) return false;
12+
```
13+
14+
#### 📘 理由:
15+
16+
* **負数**(例: `-121`)は、符号があるため回文にはならない。
17+
* **末尾0の数**(例: `10`)は、反転すると `01` になり、回文でない。
18+
19+
#### 📊 イメージ:
20+
21+
```
22+
x = -121 → NG("-" がつく)
23+
24+
x = 10
25+
-> 10 を反転 → 01(≠10) → NG
26+
```
27+
28+
---
29+
30+
### Step 2: 反転した下半分の数 `reverted` を構築
31+
32+
```ts
33+
let reverted = 0;
34+
while (x > reverted) {
35+
reverted = reverted * 10 + x % 10;
36+
x = Math.floor(x / 10);
37+
}
38+
```
39+
40+
#### 🔁 数字を半分反転(下位から1桁ずつ)
41+
42+
**例:x = 1221**
43+
44+
| ループ | x | reverted | 処理内容 |
45+
| ---- | ---- | -------- | ------------------------------- |
46+
| 初期 | 1221 | 0 | |
47+
|| 122 | 1 | reverted = 0×10 + 1 |
48+
|| 12 | 12 | reverted = 1×10 + 2 |
49+
| (終了) | | | x (=12) ≯ reverted (=12) → stop |
50+
51+
#### 🖼️ 図解:
52+
53+
```
54+
1221 の右半分 "21" を左側に反転して構築
55+
56+
x = 12 ← 元の左半分
57+
reverted = 12 ← 右側の反転結果
58+
59+
x === reverted → 回文!
60+
```
61+
62+
---
63+
64+
### Step 3: 偶数・奇数桁の調整と比較
65+
66+
```ts
67+
return x === reverted || x === Math.floor(reverted / 10);
68+
```
69+
70+
#### ✅ 比較内容:
71+
72+
* 偶数桁: `x == reverted`
73+
* 奇数桁: `x == Math.floor(reverted / 10)`
74+
75+
#### 例①:x = 1221(偶数桁)
76+
77+
```
78+
→ x = 12, reverted = 12
79+
→ 12 === 12 → ✅ 回文
80+
```
81+
82+
#### 例②:x = 12321(奇数桁)
83+
84+
| 最後 | x = 123 | reverted = 123 |
85+
| ----------------- | ------- | -------------- |
86+
| 最後の桁が中央の3 → 1桁落とす | | |
87+
88+
```
89+
→ x = 12, Math.floor(123 / 10) = 12
90+
→ 12 === 12 → ✅ 回文
91+
```
92+
93+
---
94+
95+
## 🧠 なぜ半分だけ反転するのか?
96+
97+
文字列にせず、**後ろ半分の数字だけ反転して前半と比較**することで:
98+
99+
* **オーバーフロー回避**
100+
* **時間・メモリの効率化**
101+
102+
---
103+
104+
## 💡 全体フローチャート
105+
106+
```plaintext
107+
108+
入力整数 x を受け取る
109+
110+
x が負数 または 末尾0(かつ0でない)なら false
111+
112+
reverted = 0
113+
while x > reverted:
114+
reverted = reverted * 10 + x % 10
115+
x = Math.floor(x / 10)
116+
117+
x == reverted または x == Math.floor(reverted / 10)
118+
119+
Yes → true No → false
120+
```
121+
122+
---
123+
124+
## 📦 補足:メモリ&処理量の工夫点
125+
126+
* メモリ使用:O(1)(整数3つのみ使用)
127+
* 時間計算量:O(log₁₀(x))(最大で10回のループ)
128+
129+
---

0 commit comments

Comments
 (0)