Valid Number - LeetCode

Problem

  1. input: 문자열 s

  2. output: s가 유효한 숫자인지 T/F 리턴

    valid number can be split up into these components (in order):

    1. decimal number or an integer.
    2. (Optional) An 'e' or 'E', followed by an integer.

    decimal number can be split up into these components (in order):

    1. (Optional) A sign character (either '+' or '-').
    2. One of the following formats:
      1. One or more digits, followed by a dot '.'.
      2. One or more digits, followed by a dot '.', followed by one or more digits.
      3. A dot '.', followed by one or more digits.

    An integer can be split up into these components (in order):

    1. (Optional) A sign character (either '+' or '-').
    2. One or more digits.

Idea

코틀린 내장 함수를 사용하는 방법도 있지만, 내장 함수를 못 쓰게하는 경우가 많아서 구현으로 풀었다.

결국 “숫자”, “.”, “e/E” 각 경우에 대해 분기처리를 실 수 없이 하는 것이 핵심 → Sol1

Solution

  1. 구현

    각 문자에 대한 필수 조건

    “숫자”

    “e/E”

    부호

    “.”

    class Solution {
        fun isNumber(s: String): Boolean {
            var idx = 0
            var digitExist = false
            var eExist = false
            var dotExist = false
            while (idx < s.length) {
                when (s[idx]) {
                    in "0123456789" -> {
                        digitExist = true
                    }
                    in "eE" -> {
                        if (idx > 0 && (!s[idx - 1].isDigit() && s[idx - 1] != '.')) return false // e 앞은 숫자나 .
                        if (idx + 1 < s.length && (s[idx + 1] !in listOf('-', '+') && !s[idx + 1].isDigit())) return false // e 뒤는 숫자나 부호
                        if (idx == 0 || idx == s.length -1) return false // e로 시작하거나 끝날 수 없음
                        if (!digitExist || eExist) return false // 숫자가 한번도 안나왔거나 e 두개 존재 X
                        eExist = true
    
                    }
                    in "-+" -> {
                        if (idx > 0 && s[idx - 1] !in listOf('e', 'E')) return false // 부호 앞은 e
                        if (idx + 1 < s.length && (s[idx + 1] != '.' && !s[idx + 1].isDigit())) return false // 부호 뒤는 숫자나 .
                        if (idx == s.length -1) return false // 부호로 끝날 수 없음
                    }
                    '.' -> {
                        if (dotExist) return false // . 두개 존재X
                        if (idx == 0 && idx + 1 < s.length && !s[idx + 1].isDigit()) return false // .으로 시작한다면 뒤는 무조건 숫자
                        if (idx + 1 < s.length && (s[idx + 1] !in listOf('e', 'E') && !s[idx + 1].isDigit())) return false // . 뒤는 숫자나 e
                        if (s.length == 1 && s[idx] == '.') return false // .만 존재 X
                        if (eExist || dotExist) return false // e/E 뒤에 . 존재X , . 두개 존재X
                        dotExist = true
                    }
                    else -> {
                        return false
                    }
                }
                idx++
            }
            return digitExist
        }
    }
    

    시간 복잡도: 문자열 순회 = n

    Untitled

Point

  1. 조건 분기가 복잡한 경우, 각 케이스를 나눠 미리 조건을 작성하고 코드로 옮겨야 함