Skip to content

Commit c7d09a8

Browse files
committed
Add: Add question 7
1 parent a2aa65e commit c7d09a8

File tree

3 files changed

+241
-0
lines changed

3 files changed

+241
-0
lines changed

7-Reverse Integer/Note.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# 7. Reverse Integer
2+
3+
Given a signed 32-bit integer `x`, return `x` with its digits reversed.
4+
If reversing `x` causes the value to go outside the signed 32-bit integer range `[-2^31, 2^31 - 1]`, then return `0`.
5+
6+
Assume the environment does not allow you to store 64-bit integers (signed or unsigned).
7+
8+
**Constraints:**
9+
10+
- `-2^31 <= x <= 2^31 - 1`
11+
12+
## 基礎思路
13+
14+
本題要求將一個 32 位元帶符號整數的數字反轉,但反轉後的結果必須仍位於合法範圍 `[-2^31, 2^31 - 1]`,否則需回傳 `0`。在解題時需注意 JavaScript 無法使用 64 位元整數,因此不能藉由擴展精度來處理溢位問題。
15+
16+
在思考解法時,可掌握以下核心觀察:
17+
18+
- **32 位元整數上下界不對稱**
19+
`-2^31` 的絕對值大於 `2^31 - 1`,因此若直接將負數轉為正數再反轉,可能在運算過程中產生無法表示的情況。
20+
21+
- **反轉本質為逐位運算**
22+
將整數逐位分離並重新組合,每加入一位數都可能使結果超過 32 位元上下界,因此溢位檢查必須發生在每次更新之前。
23+
24+
- **符號獨立於反轉過程**
25+
正負號不影響數字本身的反轉邏輯,可先記錄符號,運算時統一用負數處理,以避免超出可表示的範圍。
26+
27+
- **僅以 32 位元的安全範圍判斷是否溢位**
28+
必須在反轉前確認下一次乘十與加位數是否會突破邊界,否則視為溢位。
29+
30+
依據以上特性,可以採用以下策略:
31+
32+
- **統一將所有運算轉換到負數空間進行**,因為負數區間的範圍較完整,不會出現負值無法表示的情況。
33+
- **逐位拆離最低位數字,並在每次合併之前進行溢位檢查**
34+
- **最終依照原始符號還原結果,若發現反轉後不能合法轉回正數,則回傳 0**
35+
36+
此策略能確保整個反轉過程始終在合法 32 位元空間內進行,安全可靠。
37+
38+
## 解題步驟
39+
40+
### Step 1:快速處理輸入為 0 的情況
41+
42+
`x` 為 0,反轉後仍為 0,無須進行任何運算,可直接回傳。
43+
44+
```typescript
45+
// 快速路徑:若輸入為 0,則可直接回傳
46+
if (x === 0) {
47+
return 0;
48+
}
49+
```
50+
51+
### Step 2:處理正負號並統一轉為負數運算
52+
53+
我們先記錄原始數是否為正數;
54+
若為正,將其轉為負數,之後所有運算都在負數區間中進行,避免處理 `-2^31` 絕對值時溢位。
55+
56+
```typescript
57+
// 紀錄此數原本是否為正
58+
let isOriginalPositive = false;
59+
60+
if (x > 0) {
61+
// 若輸入為正,則轉成負數以便於在負數範圍中安全運算
62+
isOriginalPositive = true;
63+
x = -x;
64+
}
65+
```
66+
67+
### Step 3:初始化反轉後的累積結果
68+
69+
使用 `reversedValue` 儲存目前已反轉出的數值,並保持其為非正數,與前述負數策略一致。
70+
71+
```typescript
72+
// 儲存反轉後的結果(保持為非正數以確保安全)
73+
let reversedValue = 0;
74+
```
75+
76+
### Step 4:逐位擷取原數的最低位並移除該位
77+
78+
透過 `while (x !== 0)` 不斷處理剩餘數字:
79+
每一輪先用 `% 10` 取得目前的最低位數字,再用整數除法去除該位,直到所有位數被處理完(`x` 變為 0)。
80+
81+
```typescript
82+
// 當 x 尚未處理完所有位數時持續進行
83+
while (x !== 0) {
84+
// 取出最低位數字(為負或 0)
85+
const currentDigit = x % 10;
86+
87+
// 將 x 向右移除一位(使用 32 位元向零截斷)
88+
x = (x / 10) | 0;
89+
90+
// ...
91+
}
92+
```
93+
94+
### Step 5:在加入新位數前先檢查是否會溢位
95+
96+
在將 `currentDigit` 併入 `reversedValue` 之前,
97+
先預判 `reversedValue * 10 + currentDigit` 是否會小於 32 位元可容許的最小值;
98+
若會溢位,需立刻回傳 0。
99+
100+
```typescript
101+
while (x !== 0) {
102+
// Step 4:擷取並移除最低位數字
103+
104+
// 若 reversedValue * 10 已經低於界線,則勢必溢位
105+
if (reversedValue < INT32_MIN_DIV10) {
106+
return 0;
107+
}
108+
109+
// 若已在邊界,則需進一步檢查要加入的位數是否使其超界
110+
if (reversedValue === INT32_MIN_DIV10 && currentDigit < INT32_MIN_LAST_DIGIT) {
111+
return 0;
112+
}
113+
114+
// ...
115+
}
116+
```
117+
118+
### Step 6:通過檢查後,安全地把當前位數合併進結果
119+
120+
當確定不會溢位後,才實際執行 `reversedValue * 10 + currentDigit`
121+
把新的位數接到反轉結果的尾端。
122+
123+
```typescript
124+
while (x !== 0) {
125+
// Step 4:擷取並移除最低位數字
126+
127+
// Step 5:進行溢位檢查
128+
129+
// 將此位數加入反轉結果(反轉值仍保持為負數)
130+
reversedValue = (reversedValue * 10) + currentDigit;
131+
}
132+
```
133+
134+
### Step 7:若原始輸入為正數,將結果轉回正數並再次檢查
135+
136+
如果原始 `x` 是正數,反轉完成後需再轉回正數;
137+
但若此時 `reversedValue``INT32_MIN`,則取負會超出 `INT32_MAX`,必須回傳 0。
138+
139+
```typescript
140+
// 若原輸入為正數,則需將結果取負還原
141+
if (isOriginalPositive) {
142+
// 若結果為 INT32_MIN,則無法取負(會超出 INT32_MAX),必須回傳 0
143+
if (reversedValue === INT32_MIN) {
144+
return 0;
145+
}
146+
147+
// 安全地轉回正數
148+
return -reversedValue;
149+
}
150+
```
151+
152+
### Step 8:原始為負數時,直接回傳目前結果
153+
154+
若原本就是負數,`reversedValue` 已帶有正確符號,可以直接回傳。
155+
156+
```typescript
157+
// 若原始輸入為負數,結果已為正確符號,直接回傳
158+
return reversedValue;
159+
```
160+
161+
## 時間複雜度
162+
163+
- 整數最多 10 位,每位處理一次;
164+
- 所有操作皆為常數時間。
165+
- 總時間複雜度為 $O(1)$。
166+
167+
> $O(1)$
168+
169+
## 空間複雜度
170+
171+
- 僅使用固定數量的變數;
172+
- 無任何額外陣列或動態空間。
173+
- 總空間複雜度為 $O(1)$。
174+
175+
> $O(1)$

7-Reverse Integer/answer.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Precompute 32-bit integer boundaries once for reuse in all calls
2+
const INT32_MIN = -2147483648;
3+
const INT32_MIN_DIV10 = -214748364;
4+
const INT32_MIN_LAST_DIGIT = -8;
5+
6+
/**
7+
* Reverse the digits of a signed 32-bit integer.
8+
*
9+
* @param x - The signed 32-bit integer to reverse.
10+
* @returns The reversed integer, or 0 if it would overflow 32-bit range.
11+
*/
12+
function reverse(x: number): number {
13+
// Fast path: zero remains zero without entering the loop
14+
if (x === 0) {
15+
return 0;
16+
}
17+
18+
// Record whether the original value is positive
19+
let isOriginalPositive = false;
20+
21+
if (x > 0) {
22+
// Convert positive input to negative to work in a single safe range
23+
isOriginalPositive = true;
24+
x = -x;
25+
}
26+
27+
// Accumulator for the reversed value (always kept non-positive)
28+
let reversedValue = 0;
29+
30+
// Process all digits while the value is non-zero
31+
while (x !== 0) {
32+
// Extract the least significant digit (will be negative or zero)
33+
const currentDigit = x % 10;
34+
35+
// Remove the least significant digit using 32-bit truncation toward zero
36+
x = (x / 10) | 0;
37+
38+
// Check for overflow against INT32_MIN before multiplying by 10 and adding the digit
39+
if (reversedValue < INT32_MIN_DIV10) {
40+
return 0;
41+
}
42+
43+
if (reversedValue === INT32_MIN_DIV10 && currentDigit < INT32_MIN_LAST_DIGIT) {
44+
return 0;
45+
}
46+
47+
// Safe to append the current digit to the reversed value
48+
reversedValue = (reversedValue * 10) + currentDigit;
49+
}
50+
51+
// If the original number was positive, we need to negate the result
52+
if (isOriginalPositive) {
53+
// Negating INT32_MIN would overflow to a value larger than INT32_MAX
54+
if (reversedValue === INT32_MIN) {
55+
return 0;
56+
}
57+
58+
return -reversedValue;
59+
}
60+
61+
// Original number was negative, result is already in correct sign
62+
return reversedValue;
63+
}

7-Reverse Integer/questionCode.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function reverse(x: number): number {
2+
3+
}

0 commit comments

Comments
 (0)