找出 TOP 3 的数字
目标
从一个包含字母、数字和各种符号的混合字符串中,抽取出所有有效的整数,并找出其中值最大的前三个。
数字抽取规则
在解析字符串时,一个有效的“整数”必须遵循以下规则:
-
完整性: 整数必须被完整地抽取。一个连续的数字序列应被视为一个单独的数字。
- 例如:在
"a-132b"中,应抽取出整数-132,而不是-1,3,2或32。
- 例如:在
-
负号识别: 一个负号
'-'后面紧跟着一个或多个数字时,应被视为一个负数。- 例如:
"-6"抽取出-6。 - 例如:
"@$-a"中的'-'后面不是数字,它只是一个普通的分隔符,不构成负数。
- 例如:
-
前导零处理: 输入的数字可能包含前导零(例如
01,-007)。在解析其数值时需要正确处理(例如,"01"的数值是1,"-007"的数值是-7)。 -
分隔符: 任何非数字字符(且不满足上述负号规则)都可视为数字之间的分隔符。
任务要求
- 抽取 (Extract): 从输入字符串
inputStr中,根据【数字抽取规则】找出所有整数。 - 排序 (Sort): 将所有抽出的整数按值大小进行降序排列。
- 筛选 (Select): 选取排序后列表中的前三个数。如果抽取的整数总数不足三个,则取所有抽出的整数。
解答要求
- 时间限制: 1000ms
- 内存限制: 256MB
输入格式
-
一个字符串参数
inputStr。1 <= inputStr.length <= 1000。- 仅包含可见字符(ASCII 码值 32 到 126)。
- 用例保证字符串中至少包含一个数字。
- 所包含数字的数值范围在
[-2^31, 2^31 - 1]内(即 Javaint范围内)。
输出格式
- 一个降序排列的整数序列,最多包含三个元素。
样例
输入样例 1
"a56b-6-8()_56!@$-a"
输出样例 1
[56, 56, -6]
样例 1 解释:
-
输入字符串:
"a56b-6-8()_56!@$-a" -
抽取过程:
- 遇到
'5',开始解析数字,得到56。 - 遇到
'-',其后是'6',解析为负数-6。 - 遇到
'-',其后是'8',解析为负数-8。 - 遇到
'5',开始解析数字,得到56。 - 遇到
'-',其后是'a',不是数字,因此'-'仅为分隔符。
- 遇到
-
抽取的整数列表:
[56, -6, -8, 56] -
降序排序:
[56, 56, -6, -8] -
取前三: 最终结果为
[56, 56, -6]。
输入样例 2
"--028.300003"
输出样例 2
[300003, -28]
解释:
-
输入字符串:
"--028.300003" -
抽取过程:
- 第一个
'-'后面是另一个'-',不是数字,因此第一个'-'是分隔符。 - 第二个
'-'后面是'0',开始解析负数,"-028"的数值为-28。 '.'是分隔符。- 遇到
'3',开始解析数字,得到300003。
- 第一个
-
抽取的整数列表:
[-28, 300003] -
降序排序:
[300003, -28] -
取前三: 由于总数不足三个,取所有抽出的数,结果为
[300003, -28]。
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* 实现一个从字符串中抽取最大的三个整数的系统.
*/
public class Top3Extractor {
/**
* 主方法,从输入字符串中抽取最大的三个整数.
* @param inputStr 包含可见字符的输入字符串
* @return 按值大小降序排列的最多三个整数的列表
*/
public List<Integer> extractTop3(String inputStr) {
// --- 步骤 1: 使用正则表达式抽取所有符合条件的数字字符串 ---
List<Integer> extractedNumbers = new ArrayList<>();
// 定义正则表达式模式:
// -? : 匹配一个可选的'-'字符 (用于负数)
// \d+ : 匹配一个或多个数字字符 ('0'-'9')
// 这个模式可以匹配出所有独立的整数,例如 "56", "-6", "-028"
String regex = "-?\d+";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(inputStr);
// 使用 Matcher.find() 循环查找所有匹配项
while (matcher.find()) {
// matcher.group() 获取当前匹配到的字符串
String numberStr = matcher.group();
// --- 步骤 2: 将抽取的字符串转换为整数并存储 ---
try {
// Integer.parseInt() 会自动处理负号和前导零。
// 例如,"-028" 会被正确解析为 -28。
int number = Integer.parseInt(numberStr);
extractedNumbers.add(number);
} catch (NumberFormatException e) {
// 题目保证数字范围在int内,但作为健壮性代码,可以捕获异常。
// 在本题场景下可以忽略此异常。
}
}
// --- 步骤 3: 对所有抽取的整数进行降序排序并选取前三 ---
// 使用 Stream API 进行排序和筛选:
// 1. .stream() : 创建一个流
// 2. .sorted(...) : 进行排序。Comparator.reverseOrder() 指定降序。
// 3. .limit(3) : 只取排序后的前3个元素。如果总数少于3,则取所有。
// 4. .collect(Collectors.toList()) : 将结果收集到一个新的列表中。
return extractedNumbers.stream()
.sorted(Comparator.reverseOrder())
.limit(3)
.collect(Collectors.toList());
}
}