[LeetCode] Valid Number

Validate if a given string is numeric.

Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true

Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.

這題一看就讓我會想到當年學編譯原理時寫編譯器的日子。這題實質其實就是編譯器裏的對number的詞法分析,所以想直接使用DFA。感覺這題不太可能在面試裏出現,題目不難,但是很耗時間,除非預先給出了DFA。我在這裏借用了一個別人畫的DFA,然後自己用遞歸調用的方法寫出解析方法。DFA圖如下:


首先,這個DFA其實可以簡化:通過調用String的trim方法,可以去掉首尾的多餘space,這樣可以去掉狀態8以及裏面所有標有space的有向邊。

之後,爲每一個狀態都編寫一個parse方法。在每個parse方法裏,其實就兩個部分:

第一部分是檢查讀指針是否讀到了字符串尾部。如果到了尾部,則判斷當前狀態是否爲終態:爲終態則返回true,否則返回false。

第二部分是根據當前輸入和有向邊的描述進行狀態轉移,即遞歸調用自身或者其它parse方法。如果遇到非法輸入則可以返回false。


	private boolean parseState0(char[] charArr, int i) {
		if (i == charArr.length)
			return false;

		if (Character.isDigit(charArr[i])) {
			return parseState1(charArr, i + 1);
		} else if (charArr[i] == '+' || charArr[i] == '-') {
			return parseState3(charArr, i + 1);
		} else if (charArr[i] == '.') {
			return parseState2(charArr, i + 1);
		} else {
			return false;
		}
	}

	private boolean parseState1(char[] charArr, int i) {
		if (i == charArr.length)
			return true;

		if (Character.isDigit(charArr[i])) {
			return parseState1(charArr, i + 1);
		} else if (charArr[i] == 'e' || charArr[i] == 'E') {
			return parseState5(charArr, i + 1);
		} else if (charArr[i] == '.') {
			return parseState4(charArr, i + 1);
		} else {
			return false;
		}
	}

	private boolean parseState2(char[] charArr, int i) {
		if (i == charArr.length)
			return false;

		if (Character.isDigit(charArr[i])) {
			return parseState4(charArr, i + 1);
		} else {
			return false;
		}
	}

	private boolean parseState3(char[] charArr, int i) {
		if (i == charArr.length)
			return false;

		if (Character.isDigit(charArr[i])) {
			return parseState1(charArr, i + 1);
		} else if (charArr[i] == '.') {
			return parseState2(charArr, i + 1);
		} else {
			return false;
		}
	}

	private boolean parseState4(char[] charArr, int i) {
		if (i == charArr.length)
			return true;

		if (Character.isDigit(charArr[i])) {
			return parseState4(charArr, i + 1);
		} else if (charArr[i] == 'e' || charArr[i] == 'E') {
			return parseState5(charArr, i + 1);
		} else {
			return false;
		}
	}

	private boolean parseState5(char[] charArr, int i) {
		if (i == charArr.length)
			return false;

		if (Character.isDigit(charArr[i])) {
			return parseState7(charArr, i + 1);
		} else if (charArr[i] == '+' || charArr[i] == '-') {
			return parseState6(charArr, i + 1);
		} else {
			return false;
		}
	}

	private boolean parseState6(char[] charArr, int i) {
		if (i == charArr.length)
			return false;

		if (Character.isDigit(charArr[i])) {
			return parseState7(charArr, i + 1);
		} else {
			return false;
		}
	}

	private boolean parseState7(char[] charArr, int i) {
		if (i == charArr.length)
			return true;

		if (Character.isDigit(charArr[i])) {
			return parseState7(charArr, i + 1);
		} else {
			return false;
		}
	}

    public boolean isNumber(String s) {
        if (s == null)
			return false;

		// omit the leading and trailing space
		char[] charArr = s.trim().toCharArray();

		if (charArr.length == 0)
			return false;
		else
			return parseState0(charArr, 0);
    }

個人感覺雖然代碼看起來很多,卻非常的清晰,很輕鬆的就可以一遍寫出bug free的代碼。


發佈了60 篇原創文章 · 獲贊 8 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章