在 JAVA 中删除字符串中的重复项。不允许额外的数据结构

Remove duplicates in a string in place in JAVA. No additional data structures are allowed

我最近遇到了这个问题,我实现了如下:

public class DuplicateRemover
{
    public static void removeDuplicates(char[] str)
    {
        int len = str.length;

        boolean[] hit = new boolean[256];

        for(int i = 0; i < hit.length; i++)
            hit[i] = false;

        int noDupindex = 0;

        for(int i = 0; i < len; i++)
        {
            if( !hit[str[i]] )
            {
                str[noDupindex++] = str[i];
                hit[str[i]] = true;
            }
        }
        str[noDupindex] = '[=11=]';
    }

    public static void main(String[] args)
    {
        char[] x = "hhhhhhefffff".toCharArray();
        removeDuplicates(x);
        System.out.println(x);
    }
}

但显示的输出是 "hef hhefffff"。文字 '\0' 在末尾添加到 char 数组,并且在打印时仍然打印文字 '\0' 之后的元素。为什么会这样?如果我遗漏了什么,请告诉我。

Java 字符串不以 '\0' 结尾。您正在考虑 C 和 C++。

数组的大小在创建后无法更改,因此 removeDuplicates 无法调整数组的大小。我建议 removeDuplicates returns 一个新数组,或者只是 returns 一个新的 String.

x 不是字符串对象。它是一个字符数组。当您打印一个 char 数组时,每个元素都会被打印出来。它不会停在空字符上。

除了上面的好答案,您还可以在 java 中使用 StringBuilder 来符合您的初衷,如下所示:

public class DuplicateRemover
{
    public static void removeDuplicates(StringBuilder str)
    {
        int len = str.length();

        boolean[] hit = new boolean[256];

        for(int i = 0; i < hit.length; i++)
            hit[i] = false;

        int noDupindex = 0;

        for(int i = 0; i < len; i++)
        {
            if( !hit[str.charAt(i)] )
            {
                str.setCharAt(noDupindex++, str.charAt(i));
                hit[str.charAt(i)] = true;
            }
        }
        str.delete(noDupindex, str.length());
    }

    public static void main(String[] args)
    {
        StringBuilder x = new StringBuilder("hhhhhhefffff");
        removeDuplicates(x);
        System.out.println(x);
    }
}

试试这个例子:

public static String trunc(String str) {
    char[] buff = {}, tmp = null;
    boolean found;
    for(char c : str.toLowerCase().toCharArray()) {
        found = false;
        for(char i : buff) {//search in buff for duplicate
            if(i == c) {//found duplicate
                found = true;
                break;
            }
        }
        if(!found) {//not duplicate
            tmp = buff;
            buff = new char[buff.length + 1];//new array with +1 size for new character
            System.arraycopy(tmp, 0, buff, 0, tmp.length);//copy tmp into buff
            buff[tmp.length] = c;//store the new character
        }
    }
    return new String(buff);
}

我建议使用空字符来表示何时打印。正如 immibis 指出的那样,Java 字符串不以空字符结尾。

但是您可以创建一个方法来遵守这一点。

public static void printString(final char[] str){
    int length = str.length;
    if(length == 0){
        return;
    }
    int counter = 0;
    while(counter < length && str[counter] != 0){
        System.out.print(str[counter++]);
    }
}

然后你可以这样做:

public static void main(String[] args)
{
    char[] x = "hhhhhhefffff".toCharArray();
    removeDuplicates(x);
    printString(x);
}