將整數分解為個別位數字(如 12345 → 1 2 3 4 5)是基礎位運算練習。本文對比三種經典方法:取模存陣列再反轉、遞迴分解、字串轉換,分析各自優缺點、適用場景與邊界處理。
#include <stdio.h>
void printDigitsArray(int num) {
if (num == 0) { printf("0 "); return; }
int digits[20]; // 足夠容納 64 位整數
int count = 0;
// 處理負數
bool negative = false;
if (num < 0) {
negative = true;
num = -num; // 注意 INT_MIN 絕對值溢位問題
}
// 從低位到高位取出
while (num > 0) {
digits[count++] = num % 10;
num /= 10;
}
// 輸出負號
if (negative) printf("- ");
// 反序輸出(高位到低位)
for (int i = count - 1; i >= 0; i--) {
printf("%d ", digits[i]);
}
printf("\n");
}
#include <stdio.h>
void printDigitsRecursive(int num) {
if (num < 0) {
putchar('-');
putchar(' ');
num = -num; // 同上溢位風險
}
if (num >= 10) {
printDigitsRecursive(num / 10);
}
printf("%d ", num % 10);
}
// 使用範例
int main() {
int n = 12345;
printDigitsRecursive(n); // 輸出: 1 2 3 4 5
printf("\n");
return 0;
}
#include <stdio.h>
void printDigitsString(int num) {
char buf[32];
int len = snprintf(buf, sizeof(buf), "%d", num);
for (int i = 0; i < len; i++) {
if (buf[i] == '-') printf("- ");
else printf("%c ", buf[i]);
}
printf("\n");
}
| 維度 | 陣列+反轉 | 遞迴 | 字串轉換 |
|---|---|---|---|
| 時間複雜度 | O(log₁₀ n) | O(log₁₀ n) | O(log₁₀ n) |
| 空間複雜度 | O(log₁₀ n) 陣列 | O(log₁₀ n) 呼叫棧 | O(log₁₀ n) 緩衝區 |
| 可讀性 | 中 | 高 | 最高 |
| 負數處理 | 需額外邏輯 | 需額外邏輯 | 自動處理 |
| INT_MIN 問題 | 需特殊處理 | 需特殊處理 | 無問題 |
| 適用場景 | 需進一步處理位數(如統計、修改) | 教學展示、簡單輸出 | 快速除錯、日誌輸出 |
| 執行效率 | 最快 | 函數呼叫開銷 | 格式化解析較慢 |
// INT_MIN = -2147483648,絕對值 2147483648 超過 INT_MAX (2147483647) // 直接 -num 會導致未定義行為(有號整數溢位) // 解決方案 1:使用長整型 long long val = num; if (val < 0) val = -val; // 解決方案 2:無號轉換 unsigned int uval = (num < 0) ? (unsigned int)(-num) : (unsigned int)num; // 注意:-INT_MIN 在無號下定義為 2147483648U // 解決方案 3:字串法天然免疫 snprintf(buf, sizeof(buf), "%d", INT_MIN); // 正確產生 "-2147483648"
// 統計各數字出現次數
void countDigits(int num, int count[10]) {
if (num == 0) { count[0]++; return; }
if (num < 0) num = -num; // 處理負數
while (num) {
count[num % 10]++;
num /= 10;
}
}
// 反轉整數(LeetCode 7)
int reverseInt(int x) {
long long rev = 0;
while (x) {
rev = rev * 10 + x % 10;
x /= 10;
}
return (rev > INT_MAX || rev < INT_MIN) ? 0 : (int)rev;
}
// 回文數判斷
bool isPalindrome(int x) {
if (x < 0) return false;
int original = x, reversed = 0;
while (x) {
reversed = reversed * 10 + x % 10;
x /= 10;
}
return original == reversed;
}
snprintf 字串法,正確、簡潔、免邊界煩惱。分解整數位數看似微不足道,實則蘊含進制轉換、邊界條件、遞迴與迭代轉換、字串格式化等核心概念。徹底掌握這三種方法,能舉一反三解決反轉整數、回文判斷、位數統計、大數加法等進階問題。