【问题标题】:Iterate through characters in a string and remove consecutive duplicates遍历字符串中的字符并删除连续的重复项
【发布时间】:2021-06-19 13:57:07
【问题描述】:

我正在尝试遍历一个字符串并删除连续的重复字母。

ABBACBAABCB-->AACBAABCB-->CBAABCB-->CBBCB-->CCB-->B

我的想法是遍历字符串并在 do-while 循环中删除重复项。

我的代码:

class Main {
    public static String list = "ABBACBAABCB";
    public static boolean notvalid = true;

    public static void main(String[] args) {
        do {
            String r = Iterate(list);
            isvalid(r);
            //list = r does not work
        } while (notvalid);

    }

    public static String Iterate(String str) {
        for (int i = 1; i < list.length(); i = i + 1) {
            char Curr = list.charAt(i);
            char Prev = list.charAt(i - 1);
            if (Curr == Prev) {
                String results = str.substring(0, i - 1)
                        + str.substring(i, str.length());
                return results;
            }
        }
        return str;
    }

    public static void isvalid(String str) {
        for (int i = 1; i < str.length(); i = i + 1) {
            char curr = str.charAt(i);
            char prev = str.charAt(i - 1);
            if (curr == prev) {
                notvalid = true;
                return;
            }
        }
        notvalid = false;
        return;
    }
}

显然这不起作用,它只是永远循环。

根据我收集到的信息,您不能在 java 上执行 list = results,因为字符串是不可变的。

如何用 Java 做到这一点?

【问题讨论】:

  • 由于字符串是不可变的,因此您必须通过遍历字符串并将要保留的字符复制到单独的位置来做到这一点。您如何做到这一点并跳过重复项?
  • 手动把字符串转成数组,对数组做同样的事情?
  • 您无法就地执行此操作,您需要单独的输入和输出位置。您不需要手动使用数组。
  • 我发布了我解决它的方法。如果您有更优雅的解决方案,我很感兴趣。我的感觉很复杂,而且我认为默认情况下字符串是 char 数组。
  • 字符串 "AAAB" 的预期结果是什么,如果两个 A 字符相互抵消以生成 "AB",或者三个字符全部抵消以生成 "B"

标签: java string algorithm replace duplicates


【解决方案1】:

你应该使用这样的堆栈。

static String removeConsecutiveDupplicatesLetter(String s) {
    Stack<Character> stack = new Stack<>();
    for (char c : s.toCharArray())
        if (!stack.isEmpty() && stack.peek() == c)
            stack.pop();
        else
            stack.push(c);
    return stack.stream().map(String::valueOf).collect(Collectors.joining());
}

String s = "ABBACBAABCB";
System.out.println(removeConsecutiveDupplicatesLetter(s));

结果:

B

这样工作。

stack    c
-------  -
[]       A 
[A]      B
[A B]    B
[A]      A
[]       C
[C]      B
[C B]    A
[C B A]  A
[C B]    B
[C]      C
[]       B
[B]

您也可以将char[] 用作堆栈而不是Stack

static String removeConsecutiveDupplicatesLetter(String s) {
    int length = s.length();
    char[] stack = new char[length];
    int index = 0;
    for (char c : s.toCharArray())
        if (index > 0 && stack[index - 1] == c)
            --index;
        else
            stack[index++] = c;
    return new String(stack, 0, index);
}

【讨论】:

  • 有趣,我需要导入一个库来创建这些“堆栈”吗?我可以制作任何类型的变量的堆栈吗?我在哪里可以找到有关他们方法的文档?至于你的代码逻辑,老实说,我不明白。如果有人可以确认这是有效的,我将标记为答案。提前致谢。
  • 您只能使用标准库来实现它。你应该导入java.util.Stack.Stack (Java SE 15 & JDK 15)
  • 感谢您的补充说明。我明白了逻辑,我对你返回的东西还是有点迷茫?我不熟悉流、地图和收集器。你不能只返回堆栈吗?
  • @a1a1a1a1a1 好的,我添加了更简单的解决方案。
  • 再次谢谢你,这个我完全明白了。
【解决方案2】:

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

String str = "ABBACBAABCB";

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

输出:

ABBACBAABCB
AACBAABCB
CBAABCB
CBBCB
CCB
B

解释:

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

另见:Remove a pair of chars in a string next to each other

【讨论】:

    【解决方案3】:
    class Main {
        public static String list = "ABBACBAABCB";
        public static boolean notvalid = true;
        public static char[] oList = list.toCharArray();
    
        public static void main(String[] args) {
            do {
                char[] r = Iterate(oList);
                oList = r;
                isvalid(oList);
            } while (notvalid);
    
            for (int i = 0; i < oList.length; i = i + 1) {
                System.out.print(oList[i]);
            }
        }
    
        public static char[] Iterate(char[] str) {
            for (int i = 1; i < str.length; i = i + 1) {
                char Curr = str[i];
                char Prev = str[i - 1];
                if (Curr == Prev) {
                    char[] results = removeTheElement(str, i);
                    char[] result2 = removeTheElement(results, i - 1);
                    return result2;
                }
            }
            return str;
        }
    
        public static void isvalid(char[] str) {
            for (int i = 1; i < str.length; i = i + 1) {
                char curr = str[i];
                char prev = str[i - 1];
                if (curr == prev) {
                    notvalid = true;
                    return;
                }
            }
            notvalid = false;
            return;
        }
    
        public static char[] removeTheElement(char[] arr, int index) {
            if (arr == null || index < 0 || index >= arr.length) {
                return arr;
            }
            char[] anotherArray = new char[arr.length - 1];
            for (int i = 0, k = 0; i < arr.length; i++) {
                if (i == index) {
                    continue;
                }
                anotherArray[k++] = arr[i];
            }
            return anotherArray;
        }
    }
    

    这是有效的代码。 将字符串转换为 char 数组并操作 char 数组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-05
      • 2016-07-31
      • 2019-09-02
      • 1970-01-01
      • 2015-01-26
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      相关资源
      最近更新 更多