力扣 每日一題 65. 有效數字
今天的是個困難題,但是不帶怕的,因為前一百道我都做過了,時間久了,不記得當時是怎麼做的了。
有效數字(按順序)可以分成以下幾個部分:
一個 小數 或者 整數
(可選)一個 'e' 或 'E' ,後面跟著一個 整數
小數(按順序)可以分成以下幾個部分:
(可選)一個符號字元('+' 或 '-')
下述格式之一:
至少一位數字,後面跟著一個點 '.'
至少一位數字,後面跟著一個點 '.' ,後面再跟著至少一位數字
一個點 '.' ,後面跟著至少一位數字
整數(按順序)可以分成以下幾個部分:
(可選)一個符號字元('+' 或 '-')
至少一位數字
部分有效數字列舉如下:
["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
部分無效數字列舉如下:
["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]
給你一個字串 s ,如果 s 是一個 有效數字 ,請返回 true 。
經過分析,字串總共可能的字元有以下幾種,依次分析他們的特徵。
1 點 (.),根據描述,點必須滿足前面或後面有數字,並且e|E後不可以有點;
2.e|E,前面後面必須有數字,前後數字可以帶+|-符號;
3.0~9,這個不需要特殊處理,如遇到數字,繼續遍歷即可;
4.+|-,只能在數字前,e|E之後的數字可以帶正負號。
基於上述分析,我們可以設定幾個變數,分別代表是否可以為該符號,如果不滿足條件,直接返回false,若滿足條件,一直遍歷到最後,然後返回true。
1 public boolean isNumber(String s) { 2 boolean plus = true; 3 boolean minor = true; 4 boolean dot = true; 5 boolean eValue = true; 6 char[] cs = s.toCharArray(); 7 int n =cs.length; 8 for (int i = 0; i < cs.length; i++) { 9 if(((cs[i] == '+' && plus)||(cs[i] == '-' && minor))&&i<n-1&&(cs[i+1]>='0'&&cs[i+1]<='9'||cs[i+1]=='.')) { 10 plus = false; 11 minor=false; 12 } else if ((cs[i] == 'e' || cs[i] == 'E') && eValue&&i!=cs.length-1&&i!=0) { 13 eValue = false; 14 plus = true; 15 minor = true; 16 dot=false; 17 } else if (cs[i] == '.' && dot&&((i<n-1&&cs[i+1]>='0'&&cs[i+1]<='9')||(i>0&&cs[i-1]>='0'&&cs[i-1]<='9'))) { 18 dot = false; 19 } else if (cs[i] >= '0' && cs[i] <= '9') { 20 plus = false; 21 minor=false; 22 23 continue; 24 } else { 25 return false; 26 } 27 } 28 29 return true; 30 }
程式碼有點亂,我記得《劍指offer》上有類似的題,第20題,借鑑一下,寫了個Java版本,還是比較清晰的。
1 int curr = 0; 2 public boolean isNumber(String s) { 3 s = s.trim(); 4 if (s.length() == 0) { 5 return false; 6 } 7 8 boolean isNumber = scanInteger(s); 9 if(curr<s.length()&&s.charAt(curr)=='.'){ 10 curr++; 11 isNumber = scanUnsignedInteger(s)||isNumber; 12 } 13 14 if(curr<s.length()&&(s.charAt(curr)=='E'||s.charAt(curr)=='e')){ 15 curr++; 16 isNumber = scanInteger(s)&&isNumber; 17 } 18 return isNumber&&curr==s.length(); 19 20 } 21 22 23 private boolean scanInteger(String s) { 24 if (curr < s.length() && (s.charAt(curr) == '+' || s.charAt(curr) == '-')) { 25 curr++; 26 } 27 return scanUnsignedInteger(s); 28 } 29 30 private boolean scanUnsignedInteger(String s) { 31 int tmp = curr; 32 while (curr < s.length() && s.charAt(curr) >= '0' && s.charAt(curr) <= '9') { 33 curr++; 34 } 35 return curr > tmp; 36 }