Chuyển chuỗi sang số nguyên (String to Integer - atoi)

8. String to Integer (atoi)

Đề bài

Hãy hiện thực hàm myAtoi(string s) để chuyển đổi chuỗi s thành số nguyên 32-bit có dấu (tương tự hàm atoi trong C/C++).

Thuật toán chuyển đổi:

  1. Bỏ qua các khoảng trắng ở đầu (chỉ ký tự ' ' được tính là khoảng trắng).
  2. Đọc dấu + hoặc - (nếu có) để xác định dấu của kết quả.
  3. Đọc liên tiếp các ký tự số cho tới khi gặp ký tự không phải số hoặc hết chuỗi.
  4. Chuyển phần chữ số vừa đọc thành số nguyên (ví dụ "123" -> 123, "0032" -> 32). Nếu không đọc được chữ số nào thì kết quả là 0.
  5. Nếu kết quả vượt phạm vi 32-bit có dấu [231,2311][−2^{31}, 2^{31} − 1] thì cắt về biên (clamp) tương ứng.
  6. Trả về kết quả.

Ví dụ 1:

Input: s = "42" Output: 42

Ví dụ 2:

Input: s = " -42" Output: -42

Ví dụ 3:

Input: s = "4193 with words" Output: 4193

Ví dụ 4:

Input: s = "words and 987" Output: 0

Ví dụ 5:

Input: s = "-91283472332" Output: -2147483648

Ràng buộc:

  • 0 <= s.length <= 200
  • s gồm chữ cái tiếng Anh (hoa/thường), chữ số (0-9), khoảng trắng ' ', và dấu '+', '-', '.' (tuỳ test)

Tóm tắt đề

Chuyển chuỗi s sang số nguyên theo quy tắc giống atoi:

  • Bỏ khoảng trắng đầu chuỗi.
  • Nhận diện dấu +/- (nếu có).
  • Đọc một dãy chữ số liên tục để tạo số.
  • Nếu không có chữ số → 0.
  • Nếu vượt [231,2311][−2^{31}, 2^{31} − 1] → trả về biên tương ứng.

Ý tưởng

  • Duyệt s từ trái qua phải.
  • Bỏ qua khoảng trắng đầu, sau đó xử lý dấu (nếu có).
  • Gom các chữ số liên tiếp; gặp ký tự không phải số thì dừng.
  • Chuyển dãy chữ số sang số và clamp vào phạm vi 32-bit có dấu.

Code

package leetcode func myAtoi(s string) int { maxInt, signAllowed, whitespaceAllowed, sign, digits := int64(2<<30), true, true, 1, []int{} for _, c := range s { if c == ' ' && whitespaceAllowed { continue } if signAllowed { if c == '+' { signAllowed = false whitespaceAllowed = false continue } else if c == '-' { sign = -1 signAllowed = false whitespaceAllowed = false continue } } if c < '0' || c > '9' { break } whitespaceAllowed, signAllowed = false, false digits = append(digits, int(c-48)) } var num, place int64 place, num = 1, 0 lastLeading0Index := -1 for i, d := range digits { if d == 0 { lastLeading0Index = i } else { break } } if lastLeading0Index > -1 { digits = digits[lastLeading0Index+1:] } var rtnMax int64 if sign > 0 { rtnMax = maxInt - 1 } else { rtnMax = maxInt } digitsCount := len(digits) for i := digitsCount - 1; i >= 0; i-- { num += int64(digits[i]) * place place *= 10 if digitsCount-i > 10 || num > rtnMax { return int(int64(sign) * rtnMax) } } num *= int64(sign) return int(num) }