Codingbat 挑战:maxBlock

Codingbat challenge: maxBlock

提问人:Evgeniy 提问时间:6/1/2022 最后编辑:dani-vtaEvgeniy 更新时间:6/1/2022 访问量:167

问:

给定 CodingBat 的任务 maxBlock

给定一个字符串,返回字符串中最大“块”的长度。块是一组相同的相邻字符。

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;
}

这里有什么问题?我该如何解决?enter image description here

Java 字符串

评论

2赞 tgdavies 6/1/2022
我建议您在本地运行程序并添加一些debug System.println语句(或使用调试器)并尝试弄清楚。
2赞 tgdavies 6/1/2022
(但作为一个提示:当你得到一个新的最大区块,但你还没有到达区块的尽头时,该怎么办?
0赞 user184868 6/1/2022
您必须设置 currentBlock = 0;如果字符不相等,而不是那样

答:

2赞 Robby Cornelissen 6/1/2022 #1

您未正确重置计数。如果以下字符与当前字符不同,则需要重置为。如果没有,您需要继续增加:currentBlockcurrentBlock1currentBlock

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;
}

评论

0赞 user184868 6/1/2022
是的,但是从 1 数有点愚蠢。从 0 计数并返回 maxBlock+1 对我来说看起来更清楚
2赞 Robby Cornelissen 6/1/2022
@user184868同意。除此之外,还可以进行更多改进,但希望将我的更改保持在最低限度,以免混淆原始代码的问题所在。
1赞 Eskandar Abedini 6/1/2022 #2

此代码由 IntelliJ 的 GitHub Copilot 插件生成,您只需键入,然后 GitHub Copilot 生成其余代码:int maxBlock

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;

评论

0赞 Viktor Mellgren 6/1/2022
并没有真正向操作解释问题是什么
2赞 dani-vta 6/1/2022 #3

虽然我认为 @Robby Cornelissen 和 @Eskandar Abedini 的解决方案肯定比我的解决方案更可行,并且更接近原始代码,但我想通过使用正则表达式和一些编码逻辑来提供一种不同的方法。

以下正则表达式查找字符重复出现 0 次或多次的匹配项。这可以与类的方法一起使用,以提取找到的最长匹配项。results()Matcher

这是测试正则表达式的链接

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));
}

用于测试代码的链接

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

评论

2赞 Holger 6/1/2022
你不需要像这样的结构,你可以简单地用来比较对象。然而,更简单的是使用Comparator.comparing(Integer::intValue)Comparator.naturalOrder()Integer.mapToInt(match -> match.group().length()) .max() .orElse(0)