如何改进以下算法以递归方式从字符串中从右向左删除相邻的重复字符?

时间:2014-09-19 22:59:03

标签: java string algorithm

问题陈述是以递归方式删除字符串中的重复项。 例如:abcddaacg - > abccg-> ABG

现在我实施的算法是:

保持2个指针(i和j)。我总是<学家str [j]总是元素str [i]比较删除重复项。因此,当j = 6且i = 5时,我用' \ 0'替换它们。然后我将j更新为7(c)。然后当j = 4且i = 3时(两者都是d,j得到更新导致str [4]!= str [6],因此j = i,变成j = 4)我们将它们更新为' \ 0'

当我将j更新为7时,我的问题是下一步。为此,我必须搜索下一个不是' \ 0'的字符。这就是使它成为O(n ^ 2)实现的原因。我怎样才能做得更好? O(n)

以下是代码:

static void remDups (String input) {

    char [] str = input.toCharArray();
    int j = input.length()-1;

    int i = input.length()-2;

    while (i >= 0){

        if (str[i] == str[j]) {
            str[i] = '\0';
            str[j] = '\0';
            j++;
            while (str[j] == '\0' && j < str.length) {
                j++;
            }
        } else {
            j = i;
        }
        i--;
    }

    i = 0;
    while (i < input.length()) {
        if (str[i] != '\0')
            System.out.print(str[i]);
        i++;
    }
} 

2 个答案:

答案 0 :(得分:0)

您的算法效率低下的原因在于您使用的数据结构(以及方法)会留下空白区域,而这些空白区域曾经被移除,这使得解决这些问题变得非常昂贵。我可以想到一个更有效的算法,它使用你的方法,但更好的数据结构,我也可以想到一个使用不同方法的更有效的算法。

这就像家庭作业一样,所以我宁愿你自己找到答案而不是直接给你答案,但我鼓励你弄清楚我提到的两种算法(不同的数据结构)但是算法和算法不同。如果您需要提示,请在评论中回复,我将与您合作实现目标......

编辑:我刚刚看到你的评论说匹配是从右到左,所以我的替代算法不会起作用。但是,如果允许贪婪的从左到右的比赛,我鼓励你试着弄明白它会是什么。

编辑2:此算法实际上将使用从右到左的匹配,您只需要在字符串中从右向左迭代。

答案 1 :(得分:0)

这是一个使用stack并删除char[]上的相邻重复项的迭代解决方案,因为它们更容易使用,因为String对象是不可变的。

每次迭代:

  • 使用布尔标志来跟踪是否需要删除任何相邻的重复项。

  • 将没有相等邻接的元素推入堆栈。

  • 如果我们找到相等的邻接,在它们相等的情况下递增计数器(因为你可能有两个以上相等的邻居)更新标志,说明需要删除邻接副本

  • 否则我们就完成了

  • 如果该标志被激活,我们用存储在堆栈中的非重复覆盖我们的char[]并重复循环直到没有删除重复。

以下是代码:

static char[] removeAdjDups(char[] data) {
    if (data == null) {
        return null;
    }

    Stack<Character> stack = new Stack<Character>();
    boolean removal = true; // flag keeping track if any dups were removed
    char[] temp;
    while (removal) {
        /* set removal to false */
        removal = false;

        /* push elements that don't have equal adjacents onto the stack */
        for (int i = 1; i < data.length; i++) {
            if (data[i - 1] != data[i]) {
                stack.push(data[i - 1]);
            } else {
                while (i < data.length && data[i - 1] == data[i]) {
                        i++;
                }
                /* if we found equal adjacents, activate the removal flag */
                removal = true;
            }

            if (i == data.length - 1) {
                stack.push(data[i]);
            }
        }

        /* if dups were removed
           store the array with removed adjacent dups into original data */
        if (removal) {
            temp = new char[stack.size()];
            for (int i = temp.length - 1; i >= 0; i--) {
                temp[i] = stack.pop();
            }
            data = temp;
        }
    }

    return data;
}

public static void main(String[] args) {
    String str = "abcddaacg";
    System.out.println(removeAdjDups(str.toCharArray()));
}

输出:

abg