这道题目的解法很多:
- 正则匹配
- Java类库
- 条件判断
- 有限状态机
我一开始想的解法是条件判断,后来对其进行了修改,使用了自上而下的递归:
import java.util.*; public class Solution { // 合法字符集, E视同e,因此不纳入该集合 private Set<Character> legalChars = new HashSet<>(Arrays.asList( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '.', 'e')); public boolean isNumeric (String str) { if (str == null || str.length() == 0) return false; str = str.toLowerCase(); // E视同e,简化后续逻辑 char[] charArr = str.toCharArray(); if (hasIllegalChar(charArr) // 排除不合法的字符的影响 || hasCharMoreThan(charArr, '.', 1) // .的个数不能超过1 || hasCharMoreThan(charArr, 'e', 1)) { // e的个数不能超过1 return false; } // 开始递归的时候已经进行了筛检,剩下的字符串只有合法字符,至多一个'.',至多一个'e' return doDudge(str); } // 递归辅助函数 private boolean doDudge(String str) { if (str == null || str.length() == 0) return false; if (str.contains("e")) { // 自上而下的递归,在开始递归前,确保'.'只能出现在'e'的左侧,且不能以'e'结尾 if (str.endsWith("e") || str.indexOf('.') > str.indexOf('e')) return false; return doDudge(str.split("e")[0]) && doDudge(str.split("e")[1]); } else if (str.startsWith("+") || str.startsWith("-")) { // 针对没有'e'或有'e'但是递归拆分下来的场景,确保开头最多出现一个'+'或'-' if (str.length() == 1 || str.charAt(1) == '+' || str.charAt(1) == '-') return false; // 忽略开头的'+'或者'-',继续向后递归处理 return doDudge(str.substring(1)); } else { // 递归剥离了'e'和开头的'+', '-',禁止还存在'+', '-',禁止以'.'结尾,其余均合法 return !str.endsWith(".") && !str.contains("+") && !str.contains("-"); } } // 辅助函数,判断一个数组中是否存在超过count个字符c private boolean hasCharMoreThan(char[] arr, char c, int count) { int cnt = 0; for (char ch : arr) { if (ch == c) { ++cnt; } } if (cnt > count) return true; return false; } // 辅助函数,判断字符数组中是否存在合法字符以外的字符 private boolean hasIllegalChar(char[] arr) { for (char c : arr) { if (!legalChars.contains(c)) { return true; } } return false; } }