Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从Java数组中删除重复值的最优雅的方法是什么_Java_Arrays_Algorithm_Loops - Fatal编程技术网

从Java数组中删除重复值的最优雅的方法是什么

从Java数组中删除重复值的最优雅的方法是什么,java,arrays,algorithm,loops,Java,Arrays,Algorithm,Loops,我正在尝试获取一个数组,检查是否有任何重复,并删除该字母的所有实例,我目前尝试使用的方法非常难看 榜样 In: ABBCCDE Out: ADE 或 我目前正在使用两个for循环来查找复制,将该复制的Char[]添加到另一个数组中,然后使用另外两个for循环来从我的ErrorArray中删除Char。使用SET可以自动删除任何重复的值。由于您使用的是数组,因此需要使用Arrays.asList(T..a) SET uniqueCharacters=newhashset(Arrays.asLis

我正在尝试获取一个数组,检查是否有任何重复,并删除该字母的所有实例,我目前尝试使用的方法非常难看

榜样

In: ABBCCDE
Out: ADE


我目前正在使用两个
for
循环来查找复制,将该复制的Char[]添加到另一个数组中,然后使用另外两个for循环来从我的ErrorArray中删除Char。

使用
SET
可以自动删除任何重复的值。由于您使用的是数组,因此需要使用
Arrays.asList(T..a)

SET uniqueCharacters=newhashset(Arrays.asList(yourray));

这可能是一个解决方案:

public static void main(String[] args) {
    char[] arr = { 'A', 'B', 'B', 'C', 'C', 'D', 'E' };
    Set<Character> in = new HashSet<>();
    Set<Character> dupe = new HashSet<>();
    for (char c : arr) {
        if (!dupe.contains(c)) {
            if (in.contains(c)) {
                dupe.add(c);
                in.remove(c);
            } else {
                in.add(c);
            }
        }
    }
    char[] arrR = new char[in.size()];
    int i = 0;
    for (char c : in) {
        arrR[i++] = c;
    }
    for (char c : arrR) {
        System.out.println(c);
    }
}
publicstaticvoidmain(字符串[]args){
char[]arr={'A','B','B','C','C','D','E'};
Set in=new HashSet();
Set dupe=new HashSet();
用于(字符c:arr){
如果(!重复包含(c)){
如果(在第(c)项中){
重复添加(c);
in.删除(c);
}否则{
加入(c);
}
}
}
char[]arrR=新字符[in.size()];
int i=0;
for(字符c:in){
arrR[i++]=c;
}
用于(字符c:arrR){
系统输出打印ln(c);
}
}
您没有定义优雅,但我建议使用位掩码和XOR删除重复。我认为这是优雅且极为有效的,因为它避免了为移除重复而导航集合

(这仅适用于大写字母,但易于扩展。)

这门课是这个想法的关键。它是一个围绕位集的简单包装器,用于表示当前字符或已看到的字符等:

class Bitmask {
    private static final int NUM_BITS = 26;
    private static final int OFFSET = 65;
    // e.g. {A,C,D} == [1,0,1,1,0, ...]
    BitSet bitset = new BitSet(NUM_BITS);

    public Bitmask() {}

    public Bitmask(Bitmask bitmask) {
        this.bitset = (BitSet) bitmask.bitset.clone();
    }
    public void set(char c) {
        int whichBit = (int) c - OFFSET;
        bitset.set(whichBit);        
    }

    public List<Character> getAllSet() {
        List<Character> all = new ArrayList<Character>();
        for (int i = 0; i < NUM_BITS; i++) {
            if (bitset.get(i)) {
                char c = (char) (OFFSET + i);
                all.add(new Character(c));
            }
        }        
        return all;
    }

    public void xor(Bitmask bitmask) {
        this.bitset.xor(bitmask.bitset);
    }

    public void or(Bitmask bitmask) {
        this.bitset.or(bitmask.bitset);
    }

    public void and(Bitmask bitmask) {
        this.bitset.and(bitmask.bitset);
    }

    public void andNot(Bitmask bitmask) {
        this.bitset.andNot(bitmask.bitset);
    }    
}

这个问题有很多解决方案,根据输入的不同,最佳解决方案也会有所不同

罗密狄厄斯在回答中提出的解决方案是好的,就像亚历克斯在评论Makoto的回答时提出的一样

如果你认为HasSt/HasMax有O(1)的操作,那么它们是O(n)。 然而,现实表明这种情况很少发生,这取决于哈希函数的合适程度和链表数组(或内部使用的任何结构,Java默认使用LL)的大小

例如,Java的HashMaps和HashSet在最坏情况下插入了O(n),因为它们验证重复项,从而遍历链表,而不仅仅是添加到其尾部。这仅在碰撞次数较多时发生

如果您知道输入的大小,那么最好将HashSet/HashMap的大小设置为它:HashMap(int initialCapacity)构造函数就是这样做的。这样可以防止结构的大小调整问题,这会严重影响性能

如果不这样做,它将使用默认容量。那么你只需要看散列函数有多好

一个可靠的解决方案是O(n logn)对输入进行排序,然后只迭代一次,检查数组的前一个或后一个位置是否等于所选位置,如果有,则不添加它。第二部分是O(n)。排序保证为O(nlogn),如果您使用的是Java7,它将使用非常快的timsort


如果我在面试某人,我会接受任何一种解决方案。

番石榴多组课程的合理解决方案:

    char[] chars = new char[] { 'A', 'B', 'B', 'B', 'C', 'D', 'C', 'E' };

    Multiset<Character> set =  LinkedHashMultiset.create(Chars.asList(chars));

    for (char c : chars ) {
       int cnt = set.count(c);
       if (cnt > 1) {
           set.remove(c, cnt);
       }
    }

    char[] singles = Chars.toArray(set);

    System.out.println(new String(singles));
char[]chars=新字符[]{'A','B','B','C','D','C','E'};
Multiset set=LinkedHashMultiset.create(Chars.asList(Chars));
for(char c:chars){
int cnt=设置计数(c);
如果(cnt>1){
去除(c,cnt);
}
}
char[]singles=Chars.toArray(集合);
System.out.println(新字符串(singles));
PS:使用LinkedHashMultiset而不是HashMultiset很重要,因为LinkedHashMultiset版本在迭代时保留插入顺序,而HashMultiset则不保留

我并不认为这是最节省内存的解决方案,因为创建了很多临时集合

然而,从代码的角度来看,这很简单,有人可以通过查看代码推断出您想要做什么。

  • 由于缺乏支持,基于
    Set
    的解决方案并不优雅 在Java中,用于从
    char[]
    转换为
    Set
    并返回

  • 更有效地使用上述转换所需的循环 在执行问题所需的实际处理时

  • 我认为以下解决方案的极端简单性使其变得优雅

  • 它也是有效的,尽管代价是(有点)大的数组,其大小可能是 根据所需输入字符集的知识减少

    public class Test extends TestCase {
    
        public void testDupes() {
            assertEquals("ADE", noDupes("ABBCCDE".toCharArray()));
            assertEquals("BADF", noDupes("BCACDF".toCharArray()));
        }
    
        public String noDupes(char[] in) {
            int[] count = new int[Character.MAX_VALUE];
            for (char c: in)
                count[c]++;
            StringBuffer out = new StringBuffer();
            for (char c: in)
                if (count[c]==1)
                    out.append(c);
            return out.toString();
        }
    }
    
公共静态字符串移除重复字符(字符串文本)
{
字符串sResult=“”;
char[]caText=sText.toCharArray();
int[]iaAsciiIndex=新的int[128];

对于(int i=0;i“最优雅的”是使用Java
Set
。我读过关于Set的书,我知道Set不会让我有重复,但我想删除重复的两个版本,例如ABB会变成a,因为两个“B”都会被删除为什么要同时删除两个重复?为什么不重要(有多个应用程序).我的问题是:数组是否总是像您提供的示例那样排序?因为这会改变算法drasticallyNo,它可以是任何字符串,我将编辑问题感谢+1我编码相同,本质上,我将删除我的答案。我只是建议您将第一个哈希集更改为LinkedHashSet,以防我们想要保持原始排序。我认为集合或排序是不必要的。请看我的答案。那一个很好!是的,我只是建议了一个解决方案。我稍后会分析它,但我想位掩码应该有助于解决这个问题的O(n)解决方案。你知道当出现奇数个
char[] input = {'A', 'B', 'B', 'B', 'C', 'D', 'E'};  //expect 'ACDE'
//char[] input = {'A', 'A', 'B', 'B', 'B', 'C'};
//char[] input = {'A', 'C', 'G' };

Bitmask moreThanOnceBitmask = new Bitmask();
Bitmask onceBitmask = new Bitmask();

for(char c : input) {
    Bitmask thisBitmask = new Bitmask();
    thisBitmask.set(c);
    Bitmask tmpOnceBitmask = new Bitmask(onceBitmask);
    // we've seen 'char c' at least once
    onceBitmask.or(thisBitmask);
    // we've seen 'char c' more than once
    tmpOnceBitmask.and(thisBitmask);
    moreThanOnceBitmask.or(tmpOnceBitmask);
}

// we want 'at least once' but not 'more than once'
Bitmask finalBitmask = new Bitmask(onceBitmask);
finalBitmask.andNot(moreThanOnceBitmask);

// build list

System.out.println(finalBitmask.getAllSet().toString());
    char[] chars = new char[] { 'A', 'B', 'B', 'B', 'C', 'D', 'C', 'E' };

    Multiset<Character> set =  LinkedHashMultiset.create(Chars.asList(chars));

    for (char c : chars ) {
       int cnt = set.count(c);
       if (cnt > 1) {
           set.remove(c, cnt);
       }
    }

    char[] singles = Chars.toArray(set);

    System.out.println(new String(singles));
public class Test extends TestCase {

    public void testDupes() {
        assertEquals("ADE", noDupes("ABBCCDE".toCharArray()));
        assertEquals("BADF", noDupes("BCACDF".toCharArray()));
    }

    public String noDupes(char[] in) {
        int[] count = new int[Character.MAX_VALUE];
        for (char c: in)
            count[c]++;
        StringBuffer out = new StringBuffer();
        for (char c: in)
            if (count[c]==1)
                out.append(c);
        return out.toString();
    }
}
public static String removeDuplicateChars (String sText)
{
    String sResult = "";
    char[] caText = sText.toCharArray();
    int[] iaAsciiIndex = new int[128];

    for (int i=0 ; i<caText.length; i++)
    {
        iaAsciiIndex[caText[i]] += 1;
    }

    for (int i=0 ; i<iaAsciiIndex.length ; i++)
    {
        if (iaAsciiIndex[i] == 1)
            sResult += (char)i;
    }

    return sResult;
}