LeetCode 8: สตริงเป็นจำนวนเต็ม (atoi)

Nov 13 2020

ฉันกำลังโพสต์วิธีแก้ปัญหาสำหรับ "String to Integer (atoi)" ของ LeetCode หากคุณต้องการตรวจสอบโปรดดำเนินการ ขอขอบคุณ!

ปัญหา

ใช้ atoi ซึ่งแปลงสตริงเป็นจำนวนเต็ม ฟังก์ชันแรกจะละทิ้งอักขระเว้นวรรคเท่าที่จำเป็นจนกว่าจะพบอักขระที่ไม่ใช่ช่องว่างตัวแรก จากนั้นการเริ่มต้นจากอักขระนี้จะใช้เครื่องหมายบวกหรือลบเริ่มต้นที่เป็นทางเลือกตามด้วยตัวเลขจำนวนมากที่สุดเท่าที่จะเป็นไปได้และตีความเป็นค่าตัวเลข สตริงสามารถมีอักขระเพิ่มเติมหลังจากที่เป็นจำนวนอินทิกรัลซึ่งจะถูกละเว้นและไม่มีผลต่อลักษณะการทำงานของฟังก์ชันนี้ หากลำดับแรกของอักขระที่ไม่ใช่ช่องว่างใน str ไม่ใช่จำนวนอินทิกรัลที่ถูกต้องหรือหากไม่มีลำดับดังกล่าวเนื่องจาก str ว่างเปล่าหรือมีเพียงอักขระเว้นวรรคจะไม่มีการแปลง หากไม่สามารถทำการแปลงที่ถูกต้องได้ระบบจะส่งคืนค่าเป็นศูนย์

บันทึก:

เฉพาะอักขระเว้นวรรค '' เท่านั้นที่ถือเป็นอักขระเว้นวรรค สมมติว่าเรากำลังจัดการกับสภาพแวดล้อมที่สามารถจัดเก็บเฉพาะจำนวนเต็มภายในช่วงจำนวนเต็มที่มีลายเซ็น 32 บิตเท่านั้น: [−231, 231 - 1] ถ้าค่าตัวเลขอยู่นอกช่วงของค่าที่แสดงได้ระบบจะส่งกลับ 231 - 1 หรือ −231

ตัวอย่างที่ 1:

Input: str = "42"
Output: 42

ตัวอย่างที่ 2:

Input: str = "   -42"
Output: -42
Explanation: The first non-whitespace character is '-', which is the minus sign. Then take as many numerical digits as possible, which gets 42.

ตัวอย่างที่ 3:

Input: str = "4193 with words"
Output: 4193
Explanation: Conversion stops at digit '3' as the next character is not a numerical digit.

ตัวอย่างที่ 4:

Input: str = "words and 987"
Output: 0
Explanation: The first non-whitespace character is 'w', which is not a numerical digit or a +/- sign. Therefore no valid conversion could be performed.

ตัวอย่างที่ 5:

Input: str = "-91283472332"
Output: -2147483648
Explanation: The number "-91283472332" is out of the range of a 32-bit signed integer. Thefore INT_MIN (−231) is returned.

รหัส

from typing import List
import collections
import itertools
import functools
import math
import string
import random
import bisect
import re
import operator
import heapq
import queue

from queue import PriorityQueue
from itertools import combinations, permutations
from functools import lru_cache
from collections import defaultdict
from collections import OrderedDict
from collections import deque
from collections import Counter


class Solution:
    def myAtoi(self, s):
        s = re.findall(r'^\s*[+-]?\d+', s)
        try:
            MAX, MIN = 2147483647, -2147483648
            res = int(''.join(s))
            if res > MAX:
                return MAX
            if res < MIN:
                return MIN
            return res
        except:
            return 0


if __name__ == "__main__":
    print(Solution().myAtoi("   -42"))

อ้างอิง:

  • LeetCode 8. สตริงถึงจำนวนเต็ม (atoi)

  • Leetcode atoi (สตริงเป็นจำนวนเต็ม)

คำตอบ

3 Marc Nov 13 2020 at 10:21

ทางออกที่ดีมีขนาดกะทัดรัดและเข้าใจง่าย มีข้อเสนอแนะเล็กน้อยที่ควรปรับปรุง:

  • การนำเข้า : มีการนำเข้าจำนวนมากซึ่งอาจจะเหลือจากความพยายามครั้งก่อน
  • ลองยกเว้นบล็อก : ควรอยู่รอบ ๆ รหัสที่อาจทำให้เกิดข้อยกเว้น

ใช้คำแนะนำ:

import re

class Solution:
    def myAtoi(self, s: str) -> int:
        MAX, MIN = 2147483647, -2147483648
        s = re.findall(r'^\s*[+-]?\d+', s)
        try:
            res = int(''.join(s))
        except:
            return 0
        if res > MAX:
            return MAX
        if res < MIN:
            return MIN
        return res

ประสิทธิภาพ

Runtime: 36 ms, faster than 51.56% of Python3 online submissions
Memory Usage: 14.1 MB, less than 32.27% of Python3 online submissions

Regex ทำให้โค้ดมีขนาดกะทัดรัด แต่ไม่ใช่แนวทางที่เร็วที่สุด โซลูชันที่เร็วกว่าจะวนซ้ำผ่านอักขระสตริงทีละอักขระ

1 Reinderien Nov 13 2020 at 22:22

ตัวเลขมหัศจรรย์

2147483647, -2147483648

เป็นจริง

1<<31 - 1, -(1<<31)

ซึ่งบ่งบอกเจตนาของคุณได้ดีกว่า: ขีด จำกัด ของจำนวนเต็ม 32 บิตที่ลงชื่อ

รวบรวม regex ของคุณไว้ล่วงหน้า

พิจารณาใส่ไฟล์

DIGIT_PATTERN = re.compile(r'^\s*[+-]?\d+')

ในขอบเขตทั่วโลกเพื่อให้การโทรหลายครั้งmyAtoiเร็วขึ้น

อย่าเปลือย except

คุณน่าจะแทนexcept ValueErrorซึ่งแคบกว่าและมีความหมายชัดเจนกว่า