【问题标题】:replacing all consecutive duplicates from the string with allowed no of occurrences [duplicate]用不允许出现的次数替换字符串中的所有连续重复项[重复]
【发布时间】:2019-07-16 13:42:13
【问题描述】:

我需要编写一个将字符串作为参数并返回一个新字符串的方法,该方法通过将重复相邻字母的每个实例替换为该字符串的'n' 实例而获得。

例如,如果"aaabcccd" 作为输入字符串和n =2,则返回"aabccd"。我已经尝试了以下代码,但没有得到预期的输出

String in = "aaadbbb";
char[] s = in.toCharArray();
int len = s.length;

int n = 2;
StringBuffer new_s = new StringBuffer("");
int count = 1;
char prev='\0';

for (int i = 0; i < len - 1; i++) {
    if (s[i] == s[i + 1]) {
       if(count <= n){
            new_s.append(s[i]);
           count++;
        }else{
         count=1;
       }
    } else {
        new_s.append(s[i]);
    }
}
   
System.out.println(new_s);

输出-aaadb 预期-aadbb

【问题讨论】:

  • 你能解释一下你的代码背后的逻辑吗?

标签: java string algorithm


【解决方案1】:

可以通过使用反向引用的正则表达式魔术来完成。

String in = "aaaaddbbbbc";
int n = 2;
String pattern = String.format("(([a-z])\\2{%d})\\2+", n - 1);
System.out.println(in.replaceAll(pattern, "$1"));

输出:

aaddbbc

说明: {}里面的数字是n-1

([a-z]) 是一个捕获组,匹配从 a 到 z 的任何单个小写字母。由于它是表达式中的第二组括号,因此可以将其引用为2

(([a-z])\\2{n}) 表示“匹配 n+1 次相同的字母”。它构成了第一个捕获组,我们将使用它作为替换

\\2+ 匹配同一个字母的所有额外重复。更换后丢弃。

【讨论】:

  • 非常有趣的方法。你可以调整它以适应可变长度吗?
  • 当然。更新了答案以解决这个问题。
【解决方案2】:
    public static String test(String input, int repetitions) {
    String flag = "";
    String replacement = "";
    String output = input;
    ArrayList<Character> prevLetters = new ArrayList<Character>();

    for(int x = 0; x < input.length(); x++) {
        if(!prevLetters.contains(input.charAt(x))) {
            for(int y = 0; y <= repetitions ; y++) {
                flag += String.valueOf(input.charAt(x));
            }
            if(input.contains(flag)) {
                replacement = flag.substring(0, flag.length()-1);
                while(output.contains(flag)){
                    output = output.replace(flag, replacement);
                }
            }
            flag = "";
            prevLetters.add(input.charAt(x));
        }
    }
    return output;
}

这是我的解决方案,与您的想法相似。然而,我认为与其比较每个字符值,不如简单地检查规则中的中断(字符连续出现 n+1 次)并“修复”它会更容易。

如果您对使用您的方法感兴趣,我注意到的一个潜在问题是您没有在最后一个 else 中将 count 分配给 1。您也没有机会添加最后一个字符,因为您仅在循环持续时间为 len - 1 时在索引“i”处添加字符。

【讨论】:

    【解决方案3】:

    再添加一个替代方案:

        String in = "aaadbbbjjkllllllopp";
        int n = 2;
        StringBuilder sb = new StringBuilder();
        char temp = in.charAt(0);
        for(int i = 0; i < in.length()-1;){   // note that the incrementation of i is moved to the while loop
            temp = in.charAt(i);            // save current char in temp variable
            int count = 0;
            while (i < in.length() && in.charAt(i) == temp) {   ///iterate as long as you find same chars or hit the end of the string
                i++;
                count++;
            }
            if (count > n){   // if and only if count is greater than max allowed set it to max allowed
                count = n;
            }
            for(int j = 0; j < count; j++){   // append count chars
                sb.append(temp);
            }
        }
        System.out.println(sb.toString());
    

    【讨论】:

      【解决方案4】:

      看看这个解决方案。您应该注意输入字符串中的最后一个字符,因为您只迭代到最后一个字符。

      private void replaceConsecutiveDuplicates() {
          String input = "aaadbbb";
          int n = 2;
          StringBuffer sb = new StringBuffer();
          int count = 1;
          char current;
      
          for( int i = 0; i < input.length(); ++i){
              current = input.charAt(i);
              if (i + 1 < input.length() && current == input.charAt(i + 1)) {
                  ++count;
              } else if (count > 1) {
                  for(int j = 0; j < n; ++j) {
                      sb.append(current);
                  }
                  count = 1;
              }
              else {
                  sb.append(current);
              }
          }
          System.out.println(sb.toString());
      }
      

      【讨论】:

        【解决方案5】:

        我认为你在正确的轨道上。我不确定这是否是一项作业,所以我不想直接给你答案,但这里有一些提示可能会有所帮助:

        1. 您已经在遍历字符串。这很棒!但是,我认为您想将 当前 字符与 上一个 字符进行比较,而不是下一个字符。
        2. 您无需将输入转换为 char 数组即可对其进行迭代,只需使用 charAt(idx)
        3. 您似乎从未使用过 prev,但我认为您在声明它时的想法是正确的!
        4. 将您的问题分为两部分:何时更新计数和何时追加字符。您可以在 for 循环中同时处理这两个问题,但不要尝试在同一个 if 语句中同时处理这两个问题,而是将其分解为多个 if。

        要做的三件事是:

        • 更新上一个值
        • 更新计数
        • 更新新字符串

        为这些获得正确的顺序以及我将留给你的确切实施(再次,因为我不确定这是否是一项任务)

        更新:由于其他人已发布,这是我的解决方案(带有单个 for 循环):

        private String replaceConsecutiveDuplicates(String input, int n) {
            if (input == null || input.length() < n) return input;
            if (n == 0) return "";
        
            StringBuffer sb = new StringBuffer();
        
            int count = 1;
            char prev = input.charAt(0);
            sb.append(prev);
        
            char current;
            for( int i = 1; i < input.length(); i++) {
                current = input.charAt(i);
                if (prev == current) {
                    if (++count > n) continue;
                } else {
                    count = 1; 
                }
                prev = current;
                sb.append(current);
            }
            return sb.toString();
        }
        

        【讨论】:

        • 谢谢,Alex,不过想问一下,只有一个for循环就够了吗?
        • 是的,您可以在单个 for 循环中执行此操作。 “要做的三件事”都发生在其中:)
        • 我已经用单循环解决方案更新了我的答案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-23
        • 2021-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多