題目簡介
今天的題目是經典老朋友:字串轉整數 (atoi)。
雖然名字看起來簡單,但這題其實就是一堆「麻煩的小規則」考驗你對邊界狀況的掌握。
我們要實作一個 myAtoi(String s),功能是把字串轉成一個 32-bit 整數,遵守以下規則:
忽略前導空白
判斷正負號(有 +、- 就帶上,沒寫就當正數)
讀取數字(忽略 leading zero,遇到非數字就停)
邊界檢查(小於 -2^31 回傳 -2147483648,大於 2^31-1 回傳 2147483647)
如果沒有讀到數字,回傳 0
思路
這題跟昨天的 Reverse Integer 有點像,都要小心溢出。
我大致分成這幾步:
先用 trim() 或手動掃過字串,把前導空白去掉。
看第一個字元是不是 + 或 -,決定符號。
開始逐位讀取數字,用 long 暫存,並隨時檢查是否超過範圍。
根據符號回傳結果,如果超過範圍就卡在邊界值。
程式碼 (Java)
class Solution {
public int myAtoi(String s) {
if (s == null || s.length() == 0) {
return 0;
}
int i = 0, n = s.length();
// 1. 跳過前導空白
while (i < n && s.charAt(i) == ' ') {
i++;
}
// 2. 處理正負號
int sign = 1;
if (i < n && (s.charAt(i) == '+' || s.charAt(i) == '-')) {
sign = (s.charAt(i) == '-') ? -1 : 1;
i++;
}
// 3. 轉數字
long num = 0; // 用 long 暫存,避免中間爆掉
while (i < n && Character.isDigit(s.charAt(i))) {
num = num * 10 + (s.charAt(i) - '0');
// 溢出檢查
if (sign == 1 && num > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
if (sign == -1 && -num < Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
i++;
}
return (int)(sign * num);
}
}
測試
Input: "42" → Output: 42
Input: " -042" → Output: -42
Input: "1337c0d3" → Output: 1337
Input: "0-1" → Output: 0
Input: "words 987" → Output: 0
Input: "21474836460" → Output: 2147483647 (邊界保護)
心得
這題我一開始以為只是「trim + parseInt」,結果發現根本不是 。
Java 的 Integer.parseInt() 直接爆例外,這題就是要你自己模擬 atoi。
最大的關卡就是邊界檢查,如果你沒處理 2147483647 或 -2147483648,測資會直接打臉。
做完這題之後,我覺得對「處理字串 → 整數的細節」熟悉很多,也對 LeetCode 經典坑題 有更多免疫力了。