【问题标题】:Remove a pair of chars in a string next to each other删除字符串中相邻的一对字符
【发布时间】:2021-06-29 23:23:39
【问题描述】:

在一次采访中,我遇到了一个问题,我找不到动态输入的逻辑。

输入:abbcaddaee

如果给出这个输入,我们必须删除一对字符,例如 a<b>bb</b>ca<b>dd</b>a<b>ee</b>。粗体值将被删除,输出为acaa,然后我们也必须为此做同样的事情,然后是ac<b>aa</b>。最终输出为ac

同样必须执行n 迭代次数才能删除这些相同的char 对。

输入:aabbbcffjdddd<b>aabb</b>bc<b>ff</b>j<b>dddd</b>bcj

【问题讨论】:

    标签: java string replace duplicates char


    【解决方案1】:

    您可以使用 regexp 和单个 do-while 循环

    String str = "abbcaddaee";
    
    do {
        System.out.println(str);
    } while (!str.equals(str = str.replaceAll("(.)\\1", "")));
    

    输出:

    abbcaddaee
    acaa
    ac
    

    解释:

    • regexp (.)\\1 - 任何字符后跟相同的字符;
    • str = str.replaceAll(...) - 删除所有重复并替换当前字符串;
    • !str.equals(...) - 与自身检查当前字符串的不等式,但不重复。

    另见:Iterate through a string and remove consecutive duplicates

    【讨论】:

      【解决方案2】:

      我会在这里使用正则表达式替换:

      String input = "aabbbcffjdddd";
      String output = input.replaceAll("(.)\\1", "");
      System.out.println(output);  // bcj
      

      正则表达式模式(.)\1 匹配任何单个字符,后跟同一个字符一次。我们用空字符串替换这些匹配,有效地删除它们。

      【讨论】:

      • 是的,你是对的,但我必须满足另一个条件。我们必须循环运行它,直到所有匹配项都被删除。示例:aabbbcffjdddd -> acaa -> ac 我们如何确定这个迭代次数?
      • @SankarSiva 那么是什么阻止了人们使用此代码这样做?
      • @SankarSiva 在问题中明确提出所有要求
      • 谢谢,伙计们。这是我的错。以后我会改正自己的。非常感谢您的支持:thumbsup
      【解决方案3】:

      在下面的解决方案中,我使用递归的方法给你想要的结果。

      对于模式:

      1st Capturing Group (.)
      . matches any character (except for line terminators)
      \1 matches the same text as most recently matched by the 1st capturing group
      
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      
      public class Main {
          private static Pattern p = Pattern.compile("(.)\\1");
      
          public static void main(String[] args) {
              System.out.println(removePairChar("abbcaddaee"));
              System.out.println(removePairChar("aabbbcffjdddd"));
          }
      
          public static String removePairChar(String input) {
              Matcher matcher = p.matcher(input);
              boolean matchFound = matcher.find();
              if(matchFound) {
                  input = input.replaceAll(p.pattern(), "");
                  return removePairChar(input);
              }
              return input;
          }
      
      }
      

      输出:

      ac
      bcj
      

      【讨论】:

      • 在这里使用递归是完全没有必要的,因为String#replaceAll 已经进行了全局替换。这不是在这里使用正则表达式的最有效方式。
      【解决方案4】:

      基本思想是使用堆栈。在这种情况下,我们将有 O(n) 复杂度,而不是 while + replaceAll

      1. 循环遍历字符代码,如果堆栈中不存在字符代码,则将其推送
      2. 如果栈头等于当前字符码则弹出它
      import java.util.Optional;
      import java.util.Stack;
      
      public class Main {
      
          public static void main(final String... params) {
              System.out.println(Main.normalize("abbcaddaee"));
              System.out.println(Main.normalize("aabbbcffjdddd"));
          }
      
          private static String normalize(final String input) {
              final int length = Optional.ofNullable(input).map(String::length).orElse(0);
              if (length < 2) {
                  return input;
              }
      
              Stack<Integer> buf = new Stack<Integer>();
              input.codePoints().forEach(code -> {
                  if (buf.isEmpty() || buf.peek() != code) {
                      buf.push(code);
                  } else {
                      buf.pop();
                  }
              });
      
              return buf.stream().collect(
                  StringBuilder::new,
                  StringBuilder::appendCodePoint,
                  StringBuilder::append).
                  toString();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-04
        • 2021-09-29
        • 2018-03-05
        相关资源
        最近更新 更多