公众号merlinsea
- 链接:https://leetcode.cn/problems/valid-number/
- 题目描述(自我翻译):
- 题目要求判断一个字符串是否是一个合法的数,这个数可以是整数也可以是小数也可以带e/E表示科学计数法的数字。
- 整数的要求: 整数可以是正整数,也可以是负整数。
- 小数的要求:小数必须出现小数点,且小数点两边必须至少有一边出现数字,比如【.1】是合法的,【1.】也是合法的,【1.1】也是合法的,【.】是不合法的。
- 带e/E的科学计数法的要求: e/E只能出现一次,e的前面可以是整数也可以是小数,e的后面必须是整数。比如【12e12】是合法,【12.2e-12】合法,【12.2e23.3】不合法因为e的后面必须是整数。
- 以下都是合法的数:
["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"] - 以下都是不合法的数:
[["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]]
- 解题思路:通过以上分析,可以把问题转为判断一个字符串是整数还是小数的问题。
java代码实现
/** 小数 [一定要有小数点] 1、可以有正负号[第一位] 2、点的左右至少出现一个数字 3、小数点有且仅有一个 整数 [不存在小数点] 1、可以有正负号 2、有数字 e 1、e的后面必须出现整数[可以带正负号] 2、e的前面必须出现小数或整数(可以带胜负号) 3、e/E */ class Solution { public boolean isNumber(String s) { boolean r1 = isIntNumber(s); boolean r2 = isFloatNumber(s); boolean r3 = isENumber(s); return r1 || r2 || r3; } // 判断一个数字是否带e // 234E234.3 private boolean isENumber(String s){ int idx = -1; // 用于表示e的位置 for(int i=0;i<s.length();i++){ if(s.charAt(i)=='e' || s.charAt(i)=='E'){ if(idx!=-1){ // 说明出现了两个e return false; } idx = i; } } if(idx == -1){ // 说明没有e return false; } // 保证出现了e,并且只出现一次,idx String str1 = s.substring(0,idx); // 整数或者小数 String str2 = s.substring(idx+1,s.length()); // 整数 boolean r1 = isIntNumber(str1) || isFloatNumber(str1); boolean r2 = isIntNumber(str2); return r1 && r2; } // 判断一个数字是否是小数[] private boolean isFloatNumber(String s){ if(s.length() == 0){ return false; } boolean dot = false; boolean num = false; for(int i=0;i<s.length();i++){ char ch = s.charAt(i); if(ch == '+' || ch == '-'){ if(i!=0){ return false; } }else if(ch=='.'){ if(dot){ return false; } dot = true; }else if(ch>='0' && ch<='9'){ num = true; }else{ return false; } } return dot && num; } // 判断一个数是否是整数 "+" private boolean isIntNumber(String s){ if(s.length() == 0){ return false; } boolean num = false; for(int i=0;i<s.length();i++){ char ch = s.charAt(i); if(ch == '+' || ch == '-'){ if(i!=0){ return false; } }else if(ch>='0' && ch<='9'){ num = true; }else{ return false; } } return num; } }
java代码优化
class Solution { // 以e作为分割点,前半段可以是整数或者小数,后半段只能是整数 // 数字【必须要出现】、小数点【只能出现一次】、正负号【只能出现一次,且在第一个】 // E的条件 [只能出现一次,前面必须是整数或小数,后面必须是整数] public boolean isNumber(String s) { boolean sign = false; // 是否遇见了+-号 boolean num = false; // 是否出现了数字 boolean dot = false; // 是否出现了小数点 boolean e = false; // 是否遇见了e for(int i=0;i<s.length();i++){ char ch = s.charAt(i); if(ch == '+' || ch=='-'){ if(!sign){ if(i==0 || s.charAt(i-1)=='e' || s.charAt(i-1)=='E'){ // 出现了正负号且是第一个或者e后面的第一个 sign = true; }else{ // 第一次出现了正负号但位置不对 return false; } }else{ // 出现了多次正负号 // 这里判断不了这个正负号是出现在e的两侧还是e的同一侧 return false; } }else if(ch == '.'){ if(!dot){ // 说明第一次遇见小数点 dot = true; }else{ // 说明遇见了第二次小数点 return false; } }else if(ch>='0' && ch <='9'){ num = true; }else if(ch == 'e' || ch =='E'){ // -53.5 e -93 if(!e && num){ // 说明e第一次出现并且前面出现了整数或者小数 e = true; // e的后半段必须出现整数,为了方便判断后半部分必须是整数 sign = false; // e的后面可以出现正负号 num = false; dot = true; // 虚拟点,占位 }else{ // e出现了多次,或者前面没有出现数字 return false; } }else{ return false; } } return num; } }
c++代码实现
class Solution { public: // 判断是否是一个小数、整数、带e/E bool isNumber(string s) { bool r1 = isIntNumber(s); bool r2 = isFloatNumber(s); bool r3 = isENumber(s); return r1 || r2 || r3; } // // 判断是否是一个小数、整数、带e/E,e只能出现一次 bool isENumber(string s){ if(s.size() == 0){ return false; } int idx = -1; for(int i=0;i<s.size();i++){ if(s[i]=='e' || s[i]=='E'){ if(idx==-1){ idx = i; }else{ return false; } } } if(idx == -1){ return false; } // [0,idx-1] , [idx+1,s.size()-1] string s1 = s.substr(0,idx); string s2 = s.substr(idx+1,s.size()-idx-1); bool r1 = isIntFloatNumber(s1); bool r2 = isIntNumber(s2); // 取交集 return r1 && r2; } // 判断一个数字是否是整数/小数 , [合法的数] bool isIntFloatNumber(string s){ bool isInt = isIntNumber(s); bool isFloat = isFloatNumber(s); return isFloat || isInt; } // 判断是否是小数 1.1 .1 1. // 出现点 并且 出现了数字 bool isFloatNumber(string s){ if(s.size()==0){ return false; } int i = 0; if(s[i]=='+'||s[i]=='-'){ i++; } bool number = false; bool dot = false; while(i<s.size()){ if(s[i]=='.'){ if(!dot){ dot = true; }else{ //遇见了两次点 return false; } }else if(s[i]>='0' && s[i]<='9'){ number = true; }else{ return false; } i++; } return dot && number; } // 判断是否是整数 bool isIntNumber(string s){ if(s.size()==0){ return false; } int i = 0; if(s[i]=='+' || s[i]=='-'){ i++; } // 假设s是一个整数 "+" --> return true; bool flag = false; // 表示是否出现了数字 while(i<s.size()){ if(s[i]>='0' && s[i]<='9'){ flag = true; i++; }else{ flag = false; break; } } return flag; } };
c++代码优化
class Solution { public: bool isNumber(string s) { bool sign = false; // 表示是否出现正负号 bool e = false; //表示是否出现e bool dot = false; //表示是否出现小数点 bool num = false; //表示是否出现数字 int i = 0; while(i<s.size()){ char ch = s[i]; if(ch == '+' || ch == '-'){ if(!e){ if(!num && !dot && !sign){ sign = true; }else{ return false; } }else{ if(!num && !sign){ sign = true; }else{ return false; } } }else if(ch == '.'){ if(!dot){ dot = true; }else{ return false; } }else if(ch>='0' && ch<='9'){ num = true; }else if(ch == 'e' || ch == 'E'){ //e只能出现一次,且e之前必须出现数字 if(e || !num){ return false; } //重置结果,重新判断e之后的结果 dot=true; num=false; sign=false; e=true; }else { return false; } i++; } return num; } };
vip永久班算法直播教学,手把手带你刷leetcode,详情如下:
奔跑的小梁,公众号:梁霖编程工具库leetcode刷题永久班直播教学,手把手带你刷题,价格调整通知,2022年11月14日