查找字符串中最长字符的有效方法

时间:2019-09-26 15:23:17

标签: java algorithm

这段代码可以正常工作,但是我正在寻找一种优化它的方法。如果查看长字符串,可以看到“ l”连续出现五次。没有其他角色连续多次出现。因此,输出为5。现在,问题是此方法检查每个字符,即使找到最大值,它也会继续检查其余字符。有没有更有效的方法?

public class Main {
    public static void main(String[] args) {
        System.out.println(longestStreak("KDDiiigllllldddfnnlleeezzeddd"));
    }
    private static int longestStreak(String str) {
        int max = 0;
        for (int i = 0; i < str.length(); i++) {
            int count = 0;
            for (int j = i; j < str.length(); j++) {
                if (str.charAt(i) == str.charAt(j)) {
                    count++;
                } else break;
            }
            if (count > max) max = count;
        }
        return max;
    }
}

5 个答案:

答案 0 :(得分:3)

我们可以在单次迭代中为先前的字符数添加变量。另外,如果i + max - currentLenght < str.length(),我们将停止迭代。这意味着无法更改最大值:

private static int longestStreak(String str) {
    int maxLenght = 0;
    int currentLenght = 1;
    char prev = str.charAt(0);
    for (int index = 1; index < str.length() && isMaxCanBeChanged(str, maxLenght, currentLenght, index); index++) {
        char currentChar = str.charAt(index);
        if (currentChar == prev) {
            currentLenght++;
        } else {
            maxLenght = Math.max(maxLenght, currentLenght);
            currentLenght = 1;
        }
        prev = currentChar;
    }
    return Math.max(maxLenght, currentLenght);
}

private static boolean isMaxCanBeChanged(String str, int max, int currentLenght, int index) {
    return index + max - currentLenght < str.length();
}

答案 1 :(得分:1)

是的。 C ++代码:

string str = "KDDiiigllllldddfnnlleeezzeddd";
int longest_streak = 1, current_streak = 1; char longest_letter = str[0];
for (int i = 1; i < str.size(); ++i) {
    if (str[i] == str[i - 1])
        current_streak++;
    else current_streak = 1;
    if (current_streak > longest_streak) {
        longest_streak = current_streak;
        longest_letter = str[i];
    }
}
cout << "The longest streak is: " << longest_streak << " and the character is: " << longest_letter << "\n";

LE:如果需要,我可以提供它的Java代码,但我认为您可以理解。

public class Main {
    public static void main(String[] args) {
        System.out.println(longestStreak("KDDiiigllllldddfnnlleeezzeddd"));
    }
    private static int longestStreak(String str) {
        int longest_streak = 1, current_streak = 1; char longest_letter = str.charAt(0);
        for (int i = 1; i < str.length(); ++i) {
            if (str.charAt(i) == str.charAt(i - 1))
                current_streak++;
            else current_streak = 1;
            if (current_streak > longest_streak) {
                longest_streak = current_streak;
                longest_letter = str.charAt(i);
            }
        }
        return longest_streak;
    }
}

答案 2 :(得分:0)

这是一个正则表达式魔术解决方案,尽管有些蛮力可能会获得一些布朗尼分数。我们可以从原始输入中的字符数开始迭代,一次减少一个,尝试对该长度的连续字符进行正则表达式替换。如果替换有效,那么我们知道条纹最长。

String input = "KDDiiigllllldddfnnlleeezzeddd";
for (int i=input.length(); i > 0; --i) {
    String replace = input.replaceAll(".*?(.)(\\1{" + (i-1) + "}).*", "$1");
    if (replace.length() != input.length()) {
        System.out.println("longest streak is: " + replace);
    }
}

此打印:

longest streak is: lllll

答案 3 :(得分:0)

可以将循环重写得更小一些,但主要是可以优化条件:

i < str.length() - max

答案 4 :(得分:0)

使用Stream和Collector。它应该给出所有重复的最高元素。

代码:

String lineString = "KDDiiiiiiigllllldddfnnlleeezzeddd";
String[] lineSplit = lineString.split("");
Map<String, Integer> collect = Arrays.stream(lineSplit)
.collect(Collectors.groupingBy(Function.identity(), Collectors.summingInt(e -> 1)));
int maxValueInMap = (Collections.max(collect.values()));
for (Entry<String, Integer> entry : collect.entrySet()) {
   if (entry.getValue() == maxValueInMap) {
      System.out.printf("Character: %s, Repetition: %d\n", entry.getKey(), entry.getValue());
   }
}

输出:

Character: i, Repetition: 7
Character: l, Repetition: 7

P.S我不确定这段代码的效率如何。我刚刚学习了Streams。