从字符串中删除重复项

时间:2013-11-16 19:32:16

标签: java string

我正在尝试从Java中的String中删除重复项。我在这里尝试了

public void unique(String s)
{
    // put your code here
    char[]newArray = s.toCharArray();

    Set<Character> uniquUsers = new HashSet<Character>();

    for (int i = 0; i < newArray.length; i++) {
        if (!uniquUsers.add(newArray[i]))
            newArray[i] =' '; 
    }
    System.out.println(new String(newArray));
}

问题是,当我尝试删除副本时,我用空格替换它。我尝试用''替换副本但是无法完成,或者我无法将重复的位置设置为null。这样做的最佳方式是什么?

6 个答案:

答案 0 :(得分:1)

如果你使用正则表达式,你只需要一行!

public void unique(String s) {
    System.out.println(s.replaceAll("(.)(?=.*\\1)", ""));
}

这将删除(通过替换为空白)后面在输入中再次找到的所有字符(通过使用前面的捕获字符的后向引用)。

答案 1 :(得分:0)

如果我理解你的问题,或许你可以尝试类似的事情:

public static String unique(final String string){
    final StringBuilder builder = new StringBuilder();
    for(final char c : string.toCharArray())
        if(builder.indexOf(Character.toString(c)) == -1)
            builder.append(c);
    return builder.toString();
}

答案 2 :(得分:0)

这适用于您正在尝试的内容。

public static void unique(String s) {
    // r code here
    char[] newArray = s.toCharArray();

    Set<Character> uniqueUsers = new HashSet<>();

    for (int i = 0; i < newArray.length; i++) {
        uniqueUsers.add(newArray[i]);
    }
    newArray = new char[uniqueUsers.size()];
    Iterator iterator = uniqueUsers.iterator();

    int i = 0;
    while (iterator.hasNext()) {
        newArray[i] = (char)iterator.next();
        i++;
    }

    System.out.println(new String(newArray));
}

答案 3 :(得分:0)

您可以使用BitSet

public String removeDuplicateChar(String str){
         if(str==null || str.equals(""))throw new NullPointerException();
         BitSet b = new BitSet(256);
         for(int i=0;i<str.length();i++){
                  b.set(str.charAt(i));
         }
         StringBuilder s = new StringBuilder();
         for(int i=0;i<256;i++){
                  if(b.isSet(i)){
                           s.append((char)i);
                  }
         }
         return s.toString();
}

您可以像下面这样滚动自己的BitSet

 class BitSet {
    int[] numbers;
    BitSet(int k){
        numbers = new int[(k >> 5) + 1];
    }
    boolean isSet(int k){
        int remender = k & 0x1F;
        int devide = k >> 5;
        return ((numbers[devide] & (1 << remender)) == 1);
    }
    void set(int k){
        int remender = k & 0x1F;
        int devide = k >> 5;
        numbers[devide] = numbers[devide] | (1 << remender);
    }
}

答案 4 :(得分:0)

不改变代码中的任何内容,更改行

System.out.println(new String(newArray));

System.out.println( new String(newArray).replaceAll(" ", ""));

添加replaceAll将删除空白

答案 5 :(得分:0)

import java.util.*;

class StrDup{

    public static void main(String[] args){

        String s = "abcdabacdabbbabbbaaaaaaaaaaaaaaaaaaabbbbbbbbbbdddddddddcccccc";
        String dup = removeDupl(s);

    }

    public static String removeDupl(String s){
  
        StringBuilder sb = new StringBuilder(s);
        String ch = "";

        for(int i = 0; i < sb.length(); i++){
            ch = sb.substring(i,i+1);
            int j = i+1;
            int k = 0;

            while(sb.indexOf(ch,j)!=-1){
                k = sb.indexOf(ch,j);
                sb.deleleCharAt(k);
                j = k;
            }
        }

        return sb.toString();
    }
}

在上面的代码中,我正在执行以下任务。

  1. 我首先将字符串转换为 stringBuilder。 Java 中的字符串是不可变的,这意味着它们就像 CD。一旦它们被创建,你就不能对它们做任何事情。他们唯一容易受到攻击的是他们的离开,即垃圾收集器结束他们的生命周期,但那是完全不同的事情。例如,

        String s = "Tanish";
        s + "is a good boy";
    

这不会做任何事情。 String s 仍然是“Tanish”。为了使第二行代码发生,您必须将操作分配给某个变量,如下所示:

       s = s + "is a good boy";

而且,不要搞错!我说字符串是不可变的,在这里我用一些新字符串重新分配 s。但是,这是一个新的字符串。原始字符串“Tanish”仍在字符串池中的某个位置。可以这样想,您创建的字符串是不可变的。 “Tanish”是不可变的,但 s 是一个变量,一个引用变量。它可以指生命过程中的任何事物。因此,“Tanish”和“Tanish is a good boy”是两个独立的字符串,但 s 现在指的是后者,而不是前者。

  1. StringBuilder 是在 Java 中创建字符串的另一种方式,它们是可变的。你可以改变它们。所以,如果“Tanish”是一个 StringBuilder,它很容易受到各种操作的影响(追加、插入、删除、等等等等!)。

  2. 所以,现在我们有了 StringBuilder sb,它与 String s 相同。

  3. 我使用了一个 StringBuilder 内置方法,即 indexOf()。此方法为我找到我正在寻找的任何字符串的索引。一旦我有了索引,我就会删除该索引处的字符串。 [注意:- 我应该在该索引处说字符而不是字符串。 StringBuilder 实际上只适用于字符串。因此,当我说“该索引处的字符串”时,我的意思是“该索引处的字符”。] 请记住,StringBuilder 是可变的。这就是我可以删除字符的原因。

  4. indexOf 被重载以接受 2 个参数。 sb.indexOf(substr,index) 返回字符串在 sb (stringbuilder) 中第一次出现的位置,从 index 开始。在示例字符串中,sb.indexOf(a,1) 将给我 4。我想对 java 说的是,“返回给我 'a' 的索引,但开始从索引 1 中查找 'a' . 所以,这样我的第一个 'a' 为 0,我不想去掉。

  5. 如果你做到了这一步,你就会像砖头一样强壮。现在,我在 for 循环中所做的就是提取第 i 个位置的字符。 j 表示从哪里开始寻找提取的字符的位置。这很重要,这样我们就不会丢失我们需要的一个字符。 K代表indexOf('a',j)的结果,即'a'的第一次出现,在索引j之后。

  6. 差不多就是这样。现在,只要我们有一个字符 ch 位于字符串中(indexOf(....) 返回 -1,如果它找不到指定的字符(...或我之前指定的字符串)作为重复,我们将获得它的位置 (k),使用 deleteCharAt(k) 删除它并将 j 更新为 kie,下一个重复的 'a'(如果存在)将出现在 k 之后,即最后一次找到它的位置。

  7. 演示:=

在我举的例子中,假设我们想要摆脱重复的 c。 因此,我们将在第一个 'c' 之后开始寻找第一个 'c',即索引 3。 sb.indexOf("c",3) 会给我们 7,其中“c”在说谎。所以,k = 7. 删除它,然后将 j 设置为 k。现在,j = 7。基本上在删除字符后,后面的字符串向左移动 1。所以,现在在第 7 个位置我们有 'd',它在 8 之前。现在, k = indexOf("c",7) 并重复整个循环。另外,请记住 indexOf("c",j) 将从 j 开始查找。这意味着如果在 j 处找到“c”,它将返回 j。这就是为什么当我们提取第一个字符时,我们从字符位置之后的位置 1 开始查找。

  1. 恭喜!您已经阅读了有关从字符串中删除重复项的 looooooooooooooooooooooooooooooooooooooooooooooooonggggggggggg 解释。我希望我能让你了解这个机制。还有疑问??? Come-N-Comment :)