簡體   English   中英

在數組實現包中找到第k個最大元素

[英]finding kth largest element in an array implemented bag

我們有一個袋裝的Comparable集合,必須找到第k個最大元素。 我將集合復制到HashSet以刪除重復項,然后將HashSet轉換為要排序的數組,並因此訪問了第k個元素。 代碼可以編譯,但是測試失敗,而且我無法弄清楚出了什么問題。 有任何想法嗎?

public E kth(int k) {
    uniqueSet();
    Object[] uniqueArr = hashSet.toArray();
    startQuick(uniqueArr);
    return (E) uniqueArr[k - 1];
}

private void startQuick(Object[] uniqueArr) {
  int i = 0, j = uniqueArr.length;
  quickSort(uniqueArr, 0, j);
}

private void quickSort(Object[] uniqueArr, int i, int j) {
    int index = partition(uniqueArr, i, j);
    if (i < index - 1) {
        quickSort(rankBagArr, index - 1, j);
    }
    if (index < j) {
        quickSort(rankBagArr, i, index - 1);
    }
}

private int partition(Object[] uniqueArr, int i, int j) {
    E tmp;
    E pivot = (E) rankBagArr[(i + j) / 2];

    while (i <= j) {
        while (rankBagArr[i].compareTo(pivot) < 0) {
            i++;
        }
        while (rankBagArr[j].compareTo(pivot) > 0) {
            j--;
        }

        if (i <= j) {
            tmp = (E) rankBagArr[i];
            rankBagArr[i] = rankBagArr[j];
            rankBagArr[j] = tmp;
            i++;
            j--;
        }
    }
    return i;
}

首先,這部分很值得懷疑:

  if (i < index - 1)
        quickSort(rankBagArr, index-1 ,j);
  if (index < j)
        quickSort(rankBagArr, i, index-1);

你不是說:

  if (i < index - 1)
        quickSort(rankBagArr, i, index-1);
  if (index + 1 < j)
        quickSort(rankBagArr, index + 1, j);

我不熟悉您的分區方法,所以我不知道這是否正確。 認為我理解它,並且在檢查中看起來還可以,但是很容易得到一個錯誤,如果沒有仔細研究就很難發現。

這是我最近在C#中編寫的一種分區方法-如果需要,您應該能夠輕松地將其轉換為Java。

private static int Partition<T>(T[] array, int left, int right,
  IComparer<T> comparer) {
  // Pivot on the rightmost element to avoid an extra swap
  T pivotValue = array[right];
  int storeIndex = left;
  for (int i = left; i < right; i++) {
    if (comparer.Compare(array[i], pivotValue) < 0) {
      Swap(array, i, storeIndex);
      storeIndex++;
    }
  }
  Swap(array, right, storeIndex);
  return storeIndex;
}

static void Swap<T>(T[] array, int x, int y) {
  T tmp = array[x];
  array[x] = array[y];
  array[y] = tmp;
}

有什么理由不只是使用Arrays.sort嗎?

如果要通過排序解決問題,則

  1. 使用API​​中的排序方法(Arrays.sort或Collections.sort)。 重新發明輪子是沒有意義的。
  2. 對集合的內容進行一次排序,而不是每次尋找第k個元素時都進行排序。

快速排序分區非常適合查找第k個元素而無需對整個集合進行排序-對分區進行分區,如果最小范圍大於k,則經常將分區轉到較低范圍,如果分區小於k,則轉到較高范圍並尋找(k-較低范圍的大小)-個元素。 它比對整個集合進行排序具有更好的復雜性。 您可以在這里了解更多信息

無論如何,您的方法都具有名為uniqueArr的參數,但是您對rankBagArr執行了一些操作。 是錯字嗎? 您的代碼中沒有rankBagArr的定義。

可能您可以減少一些操作(並提高性能),並更正所看到的默認值...

從List(ArrayList)開始,您可以要求對其進行排序(使用比較器和Collections.sort(list) )。 然后,您可以循環播放並:

  • 記住最后一個要素
  • 如果發現新元素不等於,則增加一個計數器
  • 當您的計數器達到k值時,當前元素就是您的目標

暫無
暫無

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

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