用于删除Java中重复字符的算法

时间:2017-02-06 14:58:41

标签: java algorithm

我正在使用program表明

有一个字符串,由小写英文字母组成。在一个操作中,我们可以删除具有相同值的任何一对相邻字母。

例如,字符串“aabcc”在操作后将变为“aab”或“bcc”。

结果应尽可能减少。为此,我们必须多次重复上述操作。

示例:

case 1:

Input - aaabccddd
Output - abd

这里的操作顺序如下:

aaabccddd → abccddd
abccddd → abddd
abddd → abd

您可以参考上面的链接了解更多详情。

我尝试使用List来解决问题,但我认为这不是正确的方法:

import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class Solution {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        String data = scan.next();
        scan.close();

        String[] dataArr = data.split("");

        List<String> elements = Arrays.asList(data.split(""));

        for(int i=0; i< elements.size()-1; i++) {
            if(elements.get(i).equals(elements.get(i+1))) {
                elements.remove(i);
                elements.remove(i+1);
            }
        }
        System.out.println(elements);
    }
}

我收到的错误为:java.lang.UnsupportedOperationException

请帮助我解决这个问题的正确方法。

5 个答案:

答案 0 :(得分:7)

Arrays#asList创建不可修改的列表,请查看文档:

  

返回由指定数组支持的固定大小列表。

您无法从中删除元素。尝试:

List<String> elements = new ArrayList(Arrays.asList(data.split("")));

答案 1 :(得分:6)

Maroun Maroun's answer描述了代码中异常的具体原因。

比拆分列表更简单的解决方案是按字符顺序遍历字符串:

StringBuilder sb = new StringBuilder();
int i = 0;
while (i < str.length()) {
  if (i + 1 < str.length() && str.charAt(i) == str.charAt(i + 1)) {
    i += 2;
  } else {
    sb.append(str.charAt(i));
    i += 1;
  }
}
String result = sb.toString();

答案 2 :(得分:3)

既然我们已经帮助太多而且提问者已经得到答案,请允许我提供我的解决方案:

    StringBuilder result = new StringBuilder(input.length());
    for (int ix = 0; ix < input.length(); ix++) {
        char ch = input.charAt(ix);
        if (endsWith(ch, result)) {
            removeLastChar(result);
        } else {
            result.append(ch);
        }
    }
    String output = result.toString();

我一次性完成所有工作,我认为它不会太复杂(尽管它不是最少代码行的解决方案)。

我使用两种辅助方法:

private static boolean endsWith(char ch, StringBuilder buf) {
    return buf.length() > 0 && buf.charAt(buf.length() - 1) == ch;
}

private static void removeLastChar(StringBuilder buf) {
    buf.setLength(buf.length() - 1);
}

答案 3 :(得分:1)

除了@MarounMaroun的修复,你需要在删除迭代列表中的值时要小心。

for(int i=0; i< elements.size()-1; i++) {
    if(elements.get(i).equals(elements.get(i+1))) {
        elements.remove(i);
        elements.remove(i+1); // not the index you think it is 
    }
}

由于您首先删除了索引i,因此您认为位于i+1的元素现在已移回i。根据经验,在更接近开头的项目之前,更容易删除列表中的项目。你可以写:

for(int i=0; i< elements.size()-1; i++) {
    if(elements.get(i).equals(elements.get(i+1))) {
        elements.remove(i+1);
        elements.remove(i);
    }
}

或者你可以写:

for(int i=0; i< elements.size()-1; i++) {
    if(elements.get(i).equals(elements.get(i+1))) {
        elements.remove(i);
        elements.remove(i);
    }
}

答案 4 :(得分:0)

最简单的方法(上次我解决了问题)是使用正则表达式

// Somehow read input and store it in a String input
String regex = "(.)\\1";

Pattern r = Pattern.compile(regex);
Matcher m = r.matcher(input);
while (m.find()) {
    input = m.replaceAll("");
    m = r.matcher(input);
}
// check length, do other things and print

谢谢@ OleV.V。用于指出字符串转义错误