Java 将所有两倍或三倍的字母替换为单个字母

Java 将所有两倍或三倍的字母替换为单个字母,java,algorithm,Java,Algorithm,任务: 对于仅由字母组成的给定字符串:a、b和 c将所有两倍或三倍的字母替换为单个字母 我编写了这样一个代码: public static String doubleLetters(String str) { StringBuilder ret = new StringBuilder(str.length()); if (str.length() == 0) return ""; for (int i = 1; i <

任务:

对于仅由字母组成的给定字符串:a、b和 c将所有两倍或三倍的字母替换为单个字母

我编写了这样一个代码:

public static String doubleLetters(String str) {
        StringBuilder ret = new StringBuilder(str.length());
        if (str.length() == 0) return "";

        for (int i = 1; i < str.length(); i++)
        {
            if(str.charAt(i) == str.charAt(i-1) 
                    || str.charAt(i) == str.charAt(i-1) && str.charAt(i) == str.charAt(i-2))
            {
                ret.append(str.charAt(i));
            }
        }
        return ret.toString();
    }
但是,我无法定义考虑三倍字母的条件

通过输入aaabbccc,我想要abc

通过输入aabbcc,我想要abc

通过输入aaaabbbbbbccc,我想要aabbbc

重要的 不考虑转换为1个字母的字母

请帮助我如何处理此问题。

更新的响应 如果要替换三人一组,然后替换两人一组,则需要构建一个连续频率列表。有了这个列表之后,可以通过对总数应用div/mod逻辑来构建一个字符串

我包括了一个Pair类,它扩展了存储键值关联的Map.Entry

导入java.util.*; 公共类StringUtil{ 公共静态无效字符串[]args{ System.out.printlndepeaabbcc.equalsabc; System.out.printlndepeaaabbbccc.equalsabc; System.out.printlndepeaaaaabbbbbcc.equalsaabbc; } 公共静态字符串重复限制str{ 如果str==null | | str.isEmpty{ 返回str; } StringBuilder缓冲区=新的StringBuilder; 列表对=新的ArrayList; char[]chars=str.toCharArray; char curr,prev=chars[0]; int total=0,i,add3,add2; 对于i=1;i 公共类StringUtil{ 公共静态无效字符串[]args{ System.out.printlndepeaaabbbccc;//abc } 公共静态字符串重复限制str{ StringBuilder缓冲区=新的StringBuilder; char-prev=0; 对于char curr:str.toCharArray{ 如果当前=上一个{ buffer.appendcurr; 上一次=当前; } } 返回buffer.toString; } } 最新答复 如果要替换三人一组,然后替换两人一组,则需要构建一个连续频率列表。有了这个列表之后,可以通过对总数应用div/mod逻辑来构建一个字符串

我包括了一个Pair类,它扩展了存储键值关联的Map.Entry

导入java.util.*; 公共类StringUtil{ 公共静态无效字符串[]args{ System.out.printlndepeaabbcc.equalsabc; System.out.printlndepeaaabbbccc.equalsabc; System.out.printlndepeaaaaabbbbbcc.equalsaabbc; } 公共静态字符串重复限制str{ 如果str==null | | str.isEmpty{ 返回str; } StringBuilder缓冲区=新的StringBuilder; 列表对=新的ArrayList; char[]chars=str.toCharArray; char curr,prev=chars[0]; int total=0,i,add3,add2; 对于i=1;i 公共类StringUtil{ 公共静态无效字符串[]args{ System.out.printlndepeaaabbbccc;//abc } 公共静态字符串重复限制str{ StringBuilder缓冲区=新的StringBuilder; char-prev=0; 对于char curr:str.toCharArray{ 如果当前=上一个{ buffer.appendcurr; 上一次=当前; } } 返回buffer.toString; } }
现在还不完全清楚您是否只想将三个或两个字母或任何长度的重复字符替换为单个字母。我假设后者:

public static String eliminateMultipleLetters(String s) {
    StringBuilder sb = new StringBuilder(); // better for loops than concatenation
    for (int i = 0; i < s.length() - 1; i++) {
        if (s.charAt(i) != s.charAt(i + 1))
            sb.append(s.charAt(i));
    }
    sb.append(s.charAt(s.length() - 1)); // append last character
    return sb.toString();
}
编辑:只要有3个字符,就用1替换3个字符,如果可能的话,可以按如下操作逻辑非常相似,只是结尾的步骤变得更复杂:

public static String replace3or2Letters(String s) {
    if (s.length() < 2)
        return s;
    StringBuilder sb = new StringBuilder();
    int i;
    for (i = 0; i < s.length() - 2; i++) {
        sb.append(s.charAt(i));
        if (s.charAt(i) == s.charAt(i + 1)) {
            if (s.charAt(i) == s.charAt(i + 2))
                i += 2;
            else
                i++;
        }
    }
    if (i == s.length() - 2) {
        sb.append(s.charAt(s.length() - 2));
        if (s.charAt(s.length() - 2) != s.charAt(s.length() - 2))
            sb.append(s.charAt(s.length() - 1));
    } else if (i == s.length() - 1) {
        sb.append(s.charAt(s.length() - 1));
    }
    return sb.toString();
}
更优雅:

public static String replaceUpToXbySingle(String s, int x) { // x = 3 for you
    StringBuilder sb = new StringBuilder();
    char last = 'c'; // whatever
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
        if (count == 0 || s.charAt(i) != last) {
            if (count > 0)
                sb.append(last);
            last = s.charAt(i);
            count = 1;
        } else if (++count == x) {
            sb.append(last);
            count = 0;
        }
    }
    if (count > 0)
        sb.append(last);
    return sb.toString();
}

现在还不完全清楚您是否只想将三个或两个字母或任何长度的重复字符替换为单个字母。我假设后者:

public static String eliminateMultipleLetters(String s) {
    StringBuilder sb = new StringBuilder(); // better for loops than concatenation
    for (int i = 0; i < s.length() - 1; i++) {
        if (s.charAt(i) != s.charAt(i + 1))
            sb.append(s.charAt(i));
    }
    sb.append(s.charAt(s.length() - 1)); // append last character
    return sb.toString();
}
编辑:只要有3个字符,就用1替换3个字符,如果可能的话,可以按如下操作逻辑非常相似,只是结尾的步骤变得更复杂:

public static String replace3or2Letters(String s) {
    if (s.length() < 2)
        return s;
    StringBuilder sb = new StringBuilder();
    int i;
    for (i = 0; i < s.length() - 2; i++) {
        sb.append(s.charAt(i));
        if (s.charAt(i) == s.charAt(i + 1)) {
            if (s.charAt(i) == s.charAt(i + 2))
                i += 2;
            else
                i++;
        }
    }
    if (i == s.length() - 2) {
        sb.append(s.charAt(s.length() - 2));
        if (s.charAt(s.length() - 2) != s.charAt(s.length() - 2))
            sb.append(s.charAt(s.length() - 1));
    } else if (i == s.length() - 1) {
        sb.append(s.charAt(s.length() - 1));
    }
    return sb.toString();
}
更优雅:

public static String replaceUpToXbySingle(String s, int x) { // x = 3 for you
    StringBuilder sb = new StringBuilder();
    char last = 'c'; // whatever
    int count = 0;
    for (int i = 0; i < s.length(); i++) {
        if (count == 0 || s.charAt(i) != last) {
            if (count > 0)
                sb.append(last);
            last = s.charAt(i);
            count = 1;
        } else if (++count == x) {
            sb.append(last);
            count = 0;
        }
    }
    if (count > 0)
        sb.append(last);
    return sb.toString();
}

另一种方法是:计算一个字符连续出现的次数,然后将其数除以三进行批量打印

public static String doubleLetters(String str) {
        StringBuilder ret = new StringBuilder(str.length());
        if (str.length() == 0) return "";

        int count = 1;
        for (int i = 1; i < str.length(); i++)
        {
            if (str.charAt(i) == str.charAt(i-1)) {
                count++;
                continue;
            }
            for (; count > 0; count -= 3)
                ret.append(str.charAt(i-1));
            count = 1;
        }
        for (; count > 0; count -= 3)
            ret.append(str.charAt(str.length() - 1));
        return ret.toString();
    }    

另一种方法是:计算一个字符连续出现的次数,然后将其数除以三进行批量打印

public static String doubleLetters(String str) {
        StringBuilder ret = new StringBuilder(str.length());
        if (str.length() == 0) return "";

        int count = 1;
        for (int i = 1; i < str.length(); i++)
        {
            if (str.charAt(i) == str.charAt(i-1)) {
                count++;
                continue;
            }
            for (; count > 0; count -= 3)
                ret.append(str.charAt(i-1));
            count = 1;
        }
        for (; count > 0; count -= 3)
            ret.append(str.charAt(str.length() - 1));
        return ret.toString();
    }    
但是,我无法定义要考虑三倍的条件 信件

不考虑转换为1个字母的重要字母 帐户

将此问题想象为三个阶段:

首先,生成输入中出现的所有单字母、双字母或三字母的序列或流 接下来,将序列中的每个引用替换为其第一个字母 最后,将序列或流放回一个字符串实例中 为了非常容易地实现此解决方案,我将使用main方法和static helper方法,如下所示:

public static String deDupe(String input) {
    String result = generateStreamOfOccurrences(input)
        .map(occurrence -> occurrence.substring(0, 1)
        .collect(Collectors.joining());
    return result;
}

private static Stream<String> generateStreamOfOccurrences(String str) {
    String input = str;
    List<String> listOfOccs = new ArrayList<>();

    if (input != null) {
        while (input.length() > 0) {
            String occ = input.substring(0, 1);

            if (input.length() > 2 && input.substring(1, 3).equals(occ + occ)) {
                occ = input.substring(0, 3);
            }
            else if (input.length() > 1 && input.substring(1, 2).equals(occ)) {
                occ = input.substring(0, 2);
            }

            input = input.substring(occ.length());
            listOfOccs.add(occ);
        }
    }
    return listOfOccs.stream();        
}
public static String deDupe(String input) {
    String result = generateStreamOfOccurrences(input)
        .map(occurrence -> occurrence.substr(0, 1)
        .collect(Collectors.joining());
    return result;
}

private static Stream<String> generateStreamOfOccurrences(String input) {
    List<String> listOfOccs = new ArrayList<>();

    if (input != null) {
        while (input.length() > 0) {
            String occ = input.substring(0, 1);

            if (input.length() > 2 && input.substring(1, 3).equals(occ + occ))
                occ = input.substring(0, 3);
            if (input.length() > 1 && input.substring(1, 2).equals(occ))
                occ = input.substring(0, 2);

            input = input.substring(occ.length());
            listOfOccs.add(occ);
        }
    }
    return listOfOccs.stream();        
}
主要功能易于阅读。它获取字符串中出现的字母流,每个字母都是其第一个字母的一个、两个或三个。获取此流管道的工作封装在助手函数generateListOfOccurrences中。然后流中的每个元素都被只包含第一个字母的元素替换。然后将它们连接在一起形成结果

但是,我无法定义要考虑三倍的条件 信件

不考虑转换为1个字母的重要字母 帐户

将此问题想象为三个阶段:

首先,生成输入中出现的所有单字母、双字母或三字母的序列或流 接下来,将序列中的每个引用替换为其第一个字母 最后,将序列或流放回一个字符串实例中 为了非常容易地实现此解决方案,我将使用main方法和static helper方法,如下所示:

public static String deDupe(String input) {
    String result = generateStreamOfOccurrences(input)
        .map(occurrence -> occurrence.substring(0, 1)
        .collect(Collectors.joining());
    return result;
}

private static Stream<String> generateStreamOfOccurrences(String str) {
    String input = str;
    List<String> listOfOccs = new ArrayList<>();

    if (input != null) {
        while (input.length() > 0) {
            String occ = input.substring(0, 1);

            if (input.length() > 2 && input.substring(1, 3).equals(occ + occ)) {
                occ = input.substring(0, 3);
            }
            else if (input.length() > 1 && input.substring(1, 2).equals(occ)) {
                occ = input.substring(0, 2);
            }

            input = input.substring(occ.length());
            listOfOccs.add(occ);
        }
    }
    return listOfOccs.stream();        
}
public static String deDupe(String input) {
    String result = generateStreamOfOccurrences(input)
        .map(occurrence -> occurrence.substr(0, 1)
        .collect(Collectors.joining());
    return result;
}

private static Stream<String> generateStreamOfOccurrences(String input) {
    List<String> listOfOccs = new ArrayList<>();

    if (input != null) {
        while (input.length() > 0) {
            String occ = input.substring(0, 1);

            if (input.length() > 2 && input.substring(1, 3).equals(occ + occ))
                occ = input.substring(0, 3);
            if (input.length() > 1 && input.substring(1, 2).equals(occ))
                occ = input.substring(0, 2);

            input = input.substring(occ.length());
            listOfOccs.add(occ);
        }
    }
    return listOfOccs.stream();        
}
主要功能易于阅读。它获取字符串中出现的字母流,每个字母都是其第一个字母的一个、两个或三个。获取此流管道的工作封装在助手函数generateListOfOccurrences中。然后流中的每个元素都被只包含第一个字母的元素替换。然后将它们连接在一起形成结果

但是,我无法定义要考虑三倍的条件 信件

不考虑转换为1个字母的重要字母 帐户

将此问题想象为三个阶段:

首先,生成输入中出现的所有单字母、双字母或三字母的序列或流 接下来,将序列中的每个引用替换为其第一个字母 最后,将序列或流放回一个字符串实例中 为了非常容易地实现这个解决方案,我将使用一个main方法 d静态助手方法,如下所示:

public static String deDupe(String input) {
    String result = generateStreamOfOccurrences(input)
        .map(occurrence -> occurrence.substring(0, 1)
        .collect(Collectors.joining());
    return result;
}

private static Stream<String> generateStreamOfOccurrences(String str) {
    String input = str;
    List<String> listOfOccs = new ArrayList<>();

    if (input != null) {
        while (input.length() > 0) {
            String occ = input.substring(0, 1);

            if (input.length() > 2 && input.substring(1, 3).equals(occ + occ)) {
                occ = input.substring(0, 3);
            }
            else if (input.length() > 1 && input.substring(1, 2).equals(occ)) {
                occ = input.substring(0, 2);
            }

            input = input.substring(occ.length());
            listOfOccs.add(occ);
        }
    }
    return listOfOccs.stream();        
}
public static String deDupe(String input) {
    String result = generateStreamOfOccurrences(input)
        .map(occurrence -> occurrence.substr(0, 1)
        .collect(Collectors.joining());
    return result;
}

private static Stream<String> generateStreamOfOccurrences(String input) {
    List<String> listOfOccs = new ArrayList<>();

    if (input != null) {
        while (input.length() > 0) {
            String occ = input.substring(0, 1);

            if (input.length() > 2 && input.substring(1, 3).equals(occ + occ))
                occ = input.substring(0, 3);
            if (input.length() > 1 && input.substring(1, 2).equals(occ))
                occ = input.substring(0, 2);

            input = input.substring(occ.length());
            listOfOccs.add(occ);
        }
    }
    return listOfOccs.stream();        
}
主要功能易于阅读。它获取字符串中出现的字母流,每个字母都是其第一个字母的一个、两个或三个。获取此流管道的工作封装在助手函数generateListOfOccurrences中

但是,我无法定义要考虑三倍的条件 信件

不考虑转换为1个字母的重要字母 帐户

将此问题想象为三个阶段:

首先,生成输入中出现的所有单字母、双字母或三字母的序列或流 接下来,将序列中的每个引用替换为其第一个字母 最后,将序列或流放回一个字符串实例中 为了非常容易地实现此解决方案,我将使用main方法和static helper方法,如下所示:

public static String deDupe(String input) {
    String result = generateStreamOfOccurrences(input)
        .map(occurrence -> occurrence.substring(0, 1)
        .collect(Collectors.joining());
    return result;
}

private static Stream<String> generateStreamOfOccurrences(String str) {
    String input = str;
    List<String> listOfOccs = new ArrayList<>();

    if (input != null) {
        while (input.length() > 0) {
            String occ = input.substring(0, 1);

            if (input.length() > 2 && input.substring(1, 3).equals(occ + occ)) {
                occ = input.substring(0, 3);
            }
            else if (input.length() > 1 && input.substring(1, 2).equals(occ)) {
                occ = input.substring(0, 2);
            }

            input = input.substring(occ.length());
            listOfOccs.add(occ);
        }
    }
    return listOfOccs.stream();        
}
public static String deDupe(String input) {
    String result = generateStreamOfOccurrences(input)
        .map(occurrence -> occurrence.substr(0, 1)
        .collect(Collectors.joining());
    return result;
}

private static Stream<String> generateStreamOfOccurrences(String input) {
    List<String> listOfOccs = new ArrayList<>();

    if (input != null) {
        while (input.length() > 0) {
            String occ = input.substring(0, 1);

            if (input.length() > 2 && input.substring(1, 3).equals(occ + occ))
                occ = input.substring(0, 3);
            if (input.length() > 1 && input.substring(1, 2).equals(occ))
                occ = input.substring(0, 2);

            input = input.substring(occ.length());
            listOfOccs.add(occ);
        }
    }
    return listOfOccs.stream();        
}


主要功能易于阅读。它获取字符串中出现的字母流,每个字母都是其第一个字母的一个、两个或三个。获取此流管道的工作封装在助手函数generateListOfOccurrences中。

您是否尝试过类似于/[a-z]\1+/gi?@Mr.polywhill的正则表达式?我听说过正则表达式,但我不想有意识地使用它们。我想把重点放在循环和简单的事情上,因为正如你们所看到的,我对它们有问题……由于你们之前的评论,@FlappyCat,我想你们是在试图解决某种编程测试,所以我只给你们一个提示。在IF语句中添加第三个或,即测试三元组,仅当i输入aaaaa时会发生什么?@KonstantinYovkov i应该得到两个字母“a”,前3个字母“a”将转换为1个字母“a”,然后,其余两个将转换为1个字母“a”。您是否尝试过类似于/[a-z]的正则表达式\1+/gi?@polywhill先生我听说过规则表达,但我不想有意识地使用它们。我想把重点放在循环和简单的事情上,因为正如你们所看到的,我对它们有问题……由于你们之前的评论,@FlappyCat,我想你们是在试图解决某种编程测试,所以我只给你们一个提示。在你的IF语句中添加第三个或,即测试三元组,前提是我输入aaaaa时会发生什么?@KonstantinYovkov我应该得到两个字母“a”,前3个字母“a”将转换为1个字母“a”,然后,剩下的两个将转换为1个字母“a”。我没有确切解释我想要达到的效果。例如,通过输入“aaabbbccc”可以从您的代码中获得“abc”,但我应该获得“abbc”。@FlappyCat我根据您的后续示例修改了我的回答。我没有确切解释我想要达到的效果。例如,通过输入“aaabbbccc”可以从您的代码中获得“abc”,但我应该获得“abbc”。@FlappyCat我根据您的后续示例修改了我的回答。我没有确切解释我想要达到的效果。例如,输入'aaabbbccc'可以从代码中获得'abc',但我应该得到'abbc'。@FlappyCat OK修改了答案,并为此添加了一个解决方案。不是很优雅,仅能容纳2到3个字母,否则我们需要进行概括,例如,如果是2到6个字母。@FlappyCat还添加了更优雅的参数化解决方案。我没有确切解释我想要达到的效果。例如,输入'aaabbbccc'可以从代码中获得'abc',但我应该得到'abbc'。@FlappyCat OK修改了答案,并为此添加了一个解决方案。不是很优雅,仅能容纳2到3个字母,否则我们需要概括,例如,如果是2到6个字母。@FlappyCat还添加了更优雅的参数化解决方案。您确定可以这样比较子字符串吗?@ciamej比较没有问题,因为输入模板在进行所有比较之前不会发生变化,而且它是线程安全的局部变量。但是occ+occ不会生成与输入不同的字符串对象。substr1,3?@ciamej它可以而且应该生成。问题是输入中的第二个和第三个字母是否与第一个字母相同?如果是,则出现在输入的第1到第3个字母之间。但在Java中,如果要检查字符串的内容是否相同,则需要使用“等于”来比较字符串。顺便说一句,没有substr这样的方法……你确定你能像那样比较子字符串吗?@ciamej比较没有问题,因为输入模板在进行所有比较之前不会发生变化,而且它是线程安全的局部变量。但是occ+occ不会生成与输入不同的字符串对象。substr1,3?@ciamej它可以而且应该生成。问题是输入中的第二个和第三个字母是否与第一个字母相同?如果是,则出现在输入的第1到第3个字母之间 r的内容是相同的。顺便说一句,目前还没有像substr这样的方法。。。