√base10
√可以每1000用逗号分位,要出现就都出现 //大概就是for循环,然后必须要用i + 3这样吧
√必须有货币符号作为前缀:$€¥
√负数的表示:负号或者括号,但是不能重复出现。负号在货币前面
√$€的分币可以有小数点+两位小数(有小数点的话,就必须制定后面的小数),¥没有小数点
√不能有前导0,除非是0或者0.几的$€
// 0
// $€0.25
// -$€0.25
// ($€0.25)
//总结就是$€0.可以,$€0不行
√不能有前导空白、尾随空白
√不能有其它的无效字符
应该true
$450
-€23
(¥2400)
$4,500.00
€0.25
应该false的
cat
£25
$45,0
(€350
(-$3.50)
¥120.00
$-50
€43.25
$65.
€82.1
48.50
¥1200,000
package wePayOA;
import java.util.*;
public class Solution {
public boolean isCurrency(String s) {
if (s == null) return false;
if (s.length() != s.trim().length())
return false;
int n = s.length();
if (n == 0) return false;
// flags 定义一些标志
int signCount = 0;
int leftBracketCount = 0;
int rightBracketCount = 0;
int commaIdx = 0;
int preCommaIdx = 0;
boolean hasNum = false;
boolean hasPoint = false;
Set<String> symbols = new HashSet<>(Arrays.asList("$", "€", "¥"));
//必须有货币符号作为前缀:$€¥。0 || 第一位是 || 负号就第二位是
if ((s.length() == 1 && !s.equals("0")) ||
(s.length() == 2 && !symbols.contains(Character.toString(s.charAt(0)))) ||
(s.length() > 2 && (s.contains("(") || s.contains("-")) && !symbols.contains(Character.toString(s.charAt(1)))) ||
(s.length() > 2 && (!s.contains("(") && !s.contains("-")) && !symbols.contains(Character.toString(s.charAt(0))))
)
return false;
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
// invalid character 不属于有效的字符,可以直接滚蛋了
if (!isValid(c)) return false;
// digit is always fine 数字的情况都可以标记hasNum = true
if (c >= '0' && c <= '9') hasNum = true;
// decimal place 小数点的情况
if (c == '.') {
// . cannot appear twice
//小数点不能出现两次
if (hasPoint) return false;
// if . is the last one, digits must be in front of it, e.g. "7."
//小数点如果是最后一位,前面必须有数字
if (i == n - 1 && !hasNum) return false;
hasPoint = true;
}
//美元的情况
if (c == '$') {
//$€ 不是第0 1位不行
if (i != 0 && i != 1) return false;
//如果有小数点 不是2位小数不行
if (s.contains(".")) {
if ((n - s.indexOf(".") != 3) &&
(!s.contains(")")))
return false;
if ((n - s.indexOf(".") != 4) &&
(s.contains(")")))
return false;
}
//前置0:$0.可以,$0不行
if (s.contains("$0") && !s.contains("$0."))
return false;
}
//欧元的情况
if (c == '€') {
//$€ 不是第0 1位不行
if (i != 0 && i != 1) return false;
//如果有小数点 不是2位小数不行
if (s.contains(".")) {
if ((n - s.indexOf(".") != 3) &&
(!s.contains(")")))
return false;
if ((n - s.indexOf(".") != 4) &&
(s.contains(")")))
return false;
}
//前置0:€0.可以,€0不行
if (s.contains("€0") && !s.contains("€0."))
return false;
}
//日元不能有小数点
if (c == '¥') {
if (s.contains(".")) return false;
}
// signs 减号的情况
if (c == '-') {
// no more than 2 signs 不能超过2个加减号
if (signCount == 2) return false;
// sign cannot be the last one 最后一位不能是加减号
if (i == n - 1) return false;
//其实只能是第0位吧!
if (i != 0) return false;
signCount++;
}
//括号的情况
//先把左右括号的数量分别数清楚
if (c == '(') {
leftBracketCount++;
}
if (c == ')') {
rightBracketCount++;
}
//括号的情况,左括号只能出现在第一位,不能有负号,要配对
if (c == '(') {
if (i != 0) return false;
if (signCount > 0) return false;
//提前有右括号了,不行
if (rightBracketCount > 0) return false;
}
//括号的情况,右括号只能出现在最后一位,不能有负号,要配对
if (c == ')') {
if (i != n - 1) return false;
if (signCount > 0) return false;
//左边等于0,不行
if (leftBracketCount == 0) return false;
}
//左右括号超过1个也不行
if (leftBracketCount > 1 || rightBracketCount > 1) {
return false;
}
//逗号的情况,记录第一个index,后面的index不等于它加三就不行
if (c == ',') {
preCommaIdx = commaIdx;
commaIdx = i;
//都动了的情况下
if (preCommaIdx != 0) {
if ((commaIdx - preCommaIdx) != 3) {
return false;
}
}
}
}
//最后再检查一下到逗号或者到末尾的距离
if ((commaIdx != 0) && (!s.contains(".")) && (n - commaIdx != 3))
return false;
if ((commaIdx != 0) && (s.contains(".")) && (s.indexOf('.') - commaIdx != 4))
return false;
//最后检查一下左右括号的数量是否相等
if (leftBracketCount != rightBracketCount) {
return false;
}
return true;
}
//允许的所有字符范围,加上括号、逗号、三个货币符号吧
boolean isValid(char c) {
return c == '.' || c == '-' || (c >= '0' && c <= '9') || c == ',' || c == '(' || c == ')' || c == '$' || c == '€' || c == '¥';
}
}