簡體   English   中英

沒有重復的數組,算法

[英]array without repetitions, algorithm

我必須編寫返回給定數組排序且不重復的函數。

我想出了這樣的解決方案:

 public static String [] no_repeats(String [] a)
    {
        Arrays.sort(a);

        ArrayList<String> ret = new ArrayList<>();
        for (int i =1; i < a.length; i++)
                   if(a[i].compareTo(a[i-1]) != 0)
                       ret.add(a[i]);

        return  ret.toArray(ret.toArray(new String[0]));
    }

我想知道我的問題是否有更好(更快)的解決方案? 收藏,例如。 這里不允許設置。

這個問題可以通過使用流來優雅地解決:

public static String[] no_repeats(String[] a) {
    return Arrays.stream(a)
            .distinct()
            .sorted()
            .toArray(String[]::new);
}

排序,然后檢查元素是否相等(如果相等,則它們在一起)

    public static String[] no_repeats(String[] a)
    {
        Arrays.sort(a);
        ArrayList<String> al = new ArrayList<String>();
        al.add(a[0]);
        for(int i = 1;i<a.length;i++) {
            if(!a[i].equals(a[i - 1])) {
                al.add(a[i]);
            }
        }

        return  al.toArray(new String[0]);
    }

由於您無論如何都需要進行排序,我認為這將是一個很好的方法。 該算法只是跟蹤添加的最后一個值,以確保不添加重復項。

public static String[] no_repeats(String[] a) {
    
    Arrays.sort(a);
    
    ArrayList<String> ret = new ArrayList<>();
    String lastAdded = "";
    for (String str : a) {
        if (!str.equals(lastAdded)) {
            ret.add(str);
        }
        lastAdded = str;
    }
    return ret.toArray(new String[0]);
}

當然,您可以編寫自己的最小哈希實現,以加快在自有哈希集中的查找速度。 在這種情況下,跳過重復元素后進行排序將是一種方法,因為基於哈希的查找與List.contains()調用不同,非常有效。 然后你就會對更少的項目進行排序。

以下是使用您自己的 set 實現加速該過程的方式。

  • 如果元素已經存在,則 set.add() 返回 false。
  • 所以當它返回 true 時,它​​一定是第一次遇到,所以將它添加到列表中。
  • 現在排序一個較小的列表。
  • 並返回數組。
public static String[] no_repeats(String[] a) {
    
    MiniHashSet<String> set = new MiniHashSet<>();
    
    ArrayList<String> ret = new ArrayList<>();
    
    for (String str : a) {
        if (set.add(str)) {
            ret.add(str);
        }
    }
    
    Collections.sort(ret);
    return ret.toArray(new String[0]);
}

這是一個簡單的實現,只有一個 add 和 contains 方法來加速查找過程。 哈希表的大小相當大以減少沖突的機會。

  • 此類使用對象的 hashCode 獲取適當的bucket以放置列表。
  • 每個列表可能包含散列到該桶的任何項目。 - 返回的存儲桶將是該數組索引的現有列表或以前不存在的新列表。
@SuppressWarnings("unchecked")
class MiniHashSet<T> {
    int size = 10_000;
    
    List<T>[] data = new ArrayList[size];
    
    public boolean add(T val) {
        List<T> b = getBucket(val);
        if (!b.contains(val)) {
            b.add(val);
            return true;
        }
        return false;
    }
    
    public boolean contains(T val) {
        List<T> b = getBucket(val);
        return b.contains(val);
    }
    
    private List<T> getBucket(T val) {
        int i = val.hashCode() % size;
        List<T> b = data[i];
        if (b == null) {
            b = new ArrayList<>();
            data[i] = b;
        }
        return b;
    }
}

盡管這是相當多的額外工作,但此解決方案比我提供的第一個解決方案要好得多,因為查找是有效的,並且現在可以在刪除重復項后進行排序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM