Codingbat 挑战:maxBlock
Codingbat challenge: maxBlock
鉴于来自 CodingBat 的任务 maxBlock:
给定一个字符串,return字符串中最大“块”的长度。一个块是 运行 个相同的相邻字符。
maxBlock("hoopla") → 2
maxBlock("abbCCCddBBBxx") → 3
maxBlock("") → 0
我的解决方案通过了所有测试,除了一个:
public int maxBlock(String str) {
int maxBlock = 0;
int currentBlock = 1;
if (str.length() < 1) {
return maxBlock;
} else {
maxBlock = 1;
}
for (int i = 0; i < str.length() - 1; i++) {
if (str.charAt(i) == str.charAt(i+1)) {
currentBlock++;
if (currentBlock > maxBlock) {
maxBlock = currentBlock;
currentBlock = 0;
}
}
}
return maxBlock;
}
这里有什么问题?我该如何解决?
您没有正确重置 currentBlock
计数。如果后面的字符与当前字符不同,则需要将 currentBlock
重置为 1
。如果不是,则需要继续增加currentBlock
:
public int maxBlock(String str) {
int maxBlock = 0;
int currentBlock = 1;
if (str.length() < 1) {
return maxBlock;
} else {
maxBlock = 1;
}
for (int i = 0; i < str.length() - 1; i++) {
if (str.charAt(i) == str.charAt(i+1)) {
currentBlock++;
if (currentBlock > maxBlock) {
maxBlock = currentBlock;
}
} else {
currentBlock = 1;
}
}
return maxBlock;
}
此代码由 GitHub Copilot IntelliJ 插件生成,您只需键入 int maxBlock
然后 GitHub Copilot 生成其余代码:
private int maxBlock(String s) {
if (s == null || s.length() == 0) return 0;
int maxBlocks = 0;
int currentBlocks = 0;
char currentChar = s.charAt(0);
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == currentChar) {
currentBlocks++;
} else {
currentBlocks = 1;
currentChar = s.charAt(i);
}
maxBlocks = Math.max(maxBlocks, currentBlocks);
}
return maxBlocks;
}
我只在生成的代码中添加了 if (s == null || s.length() == 0) return 0;
。
虽然我认为@Robby Cornelissen 和@Eskandar Abedini 的解决方案肯定比我的更可行并且更接近原始代码,但我想通过使用正则表达式和一些编码逻辑来提供一种不同的方法。
以下正则表达式查找字符重复出现 0 次或多次的匹配项。这可以与 Matcher
class 的 results()
方法一起使用,以提取找到的最长匹配项。
这里有一个link来测试正则表达式
https://regex101.com/r/OcMoQ9/1
代码实现
List<String> testCase = List.of("hoopla", "abbCCCddBBBxx", "", "xyz", "xxyz", "xyzz", "abbbcbbbxbbbx", "XXBBBbbxx", "XXBBBbbxxXXXX", "XX2222BBBbbXX2222");
Pattern pattern = Pattern.compile("(.)(\1*)");
Matcher matcher;
for (String s : testCase) {
matcher = pattern.matcher(s);
System.out.printf("%s => %d%n", s, matcher
.results()
.map(match -> match.group().length())
.max(Comparator.comparing(Integer::intValue))
.orElse(0));
}
//Or even simpliefied like so as @Holger has pointed out in the comments
for (String s : testCase) {
matcher = pattern.matcher(s);
System.out.printf("%s => %d%n", s, matcher
.results()
.mapToInt(match -> match.group().length())
.max()
.orElse(0));
}
Link 测试代码
https://www.jdoodle.com/iembed/v0/rH7
输出
hoopla => 2
abbCCCddBBBxx => 3
=> 0
xyz => 1
xxyz => 2
xyzz => 2
abbbcbbbxbbbx => 3
XXBBBbbxx => 3
XXBBBbbxxXXXX => 4
XX2222BBBbbXX2222 => 4
鉴于来自 CodingBat 的任务 maxBlock:
给定一个字符串,return字符串中最大“块”的长度。一个块是 运行 个相同的相邻字符。
maxBlock("hoopla") → 2
maxBlock("abbCCCddBBBxx") → 3
maxBlock("") → 0
我的解决方案通过了所有测试,除了一个:
public int maxBlock(String str) {
int maxBlock = 0;
int currentBlock = 1;
if (str.length() < 1) {
return maxBlock;
} else {
maxBlock = 1;
}
for (int i = 0; i < str.length() - 1; i++) {
if (str.charAt(i) == str.charAt(i+1)) {
currentBlock++;
if (currentBlock > maxBlock) {
maxBlock = currentBlock;
currentBlock = 0;
}
}
}
return maxBlock;
}
这里有什么问题?我该如何解决?
您没有正确重置 currentBlock
计数。如果后面的字符与当前字符不同,则需要将 currentBlock
重置为 1
。如果不是,则需要继续增加currentBlock
:
public int maxBlock(String str) {
int maxBlock = 0;
int currentBlock = 1;
if (str.length() < 1) {
return maxBlock;
} else {
maxBlock = 1;
}
for (int i = 0; i < str.length() - 1; i++) {
if (str.charAt(i) == str.charAt(i+1)) {
currentBlock++;
if (currentBlock > maxBlock) {
maxBlock = currentBlock;
}
} else {
currentBlock = 1;
}
}
return maxBlock;
}
此代码由 GitHub Copilot IntelliJ 插件生成,您只需键入 int maxBlock
然后 GitHub Copilot 生成其余代码:
private int maxBlock(String s) {
if (s == null || s.length() == 0) return 0;
int maxBlocks = 0;
int currentBlocks = 0;
char currentChar = s.charAt(0);
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == currentChar) {
currentBlocks++;
} else {
currentBlocks = 1;
currentChar = s.charAt(i);
}
maxBlocks = Math.max(maxBlocks, currentBlocks);
}
return maxBlocks;
}
我只在生成的代码中添加了 if (s == null || s.length() == 0) return 0;
。
虽然我认为@Robby Cornelissen 和@Eskandar Abedini 的解决方案肯定比我的更可行并且更接近原始代码,但我想通过使用正则表达式和一些编码逻辑来提供一种不同的方法。
以下正则表达式查找字符重复出现 0 次或多次的匹配项。这可以与 Matcher
class 的 results()
方法一起使用,以提取找到的最长匹配项。
这里有一个link来测试正则表达式
https://regex101.com/r/OcMoQ9/1
代码实现
List<String> testCase = List.of("hoopla", "abbCCCddBBBxx", "", "xyz", "xxyz", "xyzz", "abbbcbbbxbbbx", "XXBBBbbxx", "XXBBBbbxxXXXX", "XX2222BBBbbXX2222");
Pattern pattern = Pattern.compile("(.)(\1*)");
Matcher matcher;
for (String s : testCase) {
matcher = pattern.matcher(s);
System.out.printf("%s => %d%n", s, matcher
.results()
.map(match -> match.group().length())
.max(Comparator.comparing(Integer::intValue))
.orElse(0));
}
//Or even simpliefied like so as @Holger has pointed out in the comments
for (String s : testCase) {
matcher = pattern.matcher(s);
System.out.printf("%s => %d%n", s, matcher
.results()
.mapToInt(match -> match.group().length())
.max()
.orElse(0));
}
Link 测试代码
https://www.jdoodle.com/iembed/v0/rH7
输出
hoopla => 2
abbCCCddBBBxx => 3
=> 0
xyz => 1
xxyz => 2
xyzz => 2
abbbcbbbxbbbx => 3
XXBBBbbxx => 3
XXBBBbbxxXXXX => 4
XX2222BBBbbXX2222 => 4