在巨大的2D阵列中寻找第N个最大元素

时间:2014-01-30 17:43:59

标签: c arrays

我正在尝试在大型2-D阵列中找到第N个最大元素(大约850,000个元素)。 我现在使用的方法是将其转换为1-D数组,然后使用选择排序算法并以此方式找到它,但它需要的时间太长。

有人知道找到第N个最大元素的好方法,只需查看矩阵而不对其进行排序,就像找到最大的元素一样。

4 个答案:

答案 0 :(得分:3)

我认为这是某种家庭作业或面试问题,所以我只是为你制定步骤。

  1. 找到存储N个节点的适当结构。说X.(提示,快速搜索,插入,删除......)

  2. one传递中遍历矩阵,保存的值大于X中的值,并将其保存到X,并删除X中的最小值。

  3. 最后,X的最小值是N最大值。

  4. 额外空间为O(N),时间为O(size of the matrix)

答案 1 :(得分:1)

我认为随机化的quickselect应该没问题

https://en.wikipedia.org/wiki/Quickselect

平均情况O(n)

答案 2 :(得分:0)

除非您将数据结构更改为更好的数据结构(排序数组或其他内容),否则很难不迭代数组的所有元素。

从这个stackoverflow问题(Print largest number in a 2d array - why do my code print three numbers)我得到了这段代码并将其移动到C语言:

#include<limits.h>

(...)

int twodArray[XXX][YYY];
int maxValue = INT_MIN;
int yForMaxValue, xForMaxValue;
int i = 0;
    for (i = 0; i < XXX; i++) {
        for (int j = 0; j < YYY; j++)
            if (twodArray[i][j] > maxValue) {
                maxValue = twodArray[i][j];
                yForMaxValue = j;
                xForMaxValue = i;
            }
        }
    }

yForMaxValue和yForMaxValue是maxValue位置的索引。

答案 3 :(得分:0)

具有有限大小N的priority queue应该可以胜任。

将2D数组的每个元素放入队列中 O(Arraysize * log2(N))复杂度。
然后队列中的第一个元素是第N个最小元素(假设arry大小> = N)

#include <stdio.h>
#include <stdlib.h>
typedef int PriorityQueue_T;

typedef struct {
  PriorityQueue_T *A;
  size_t Length;
  size_t Size;
} PriorityQueue;

void PriorityQueue_Remove(PriorityQueue *Q) {
  if (Q->Length > 0) {
    size_t Index = 0;
    while (1) {
      size_t Mother = Index * 2 + 1;
      size_t Father = Mother + 1;
      if (Mother >= Q->Length) break;
      if ((Q->A[Mother] < Q->A[Father]) || (Father >= Q->Length)) {
        Q->A[Index] = Q->A[Mother];
        Index = Mother;
      } else {
        Q->A[Index] = Q->A[Father];
        Index = Father;
      }
    }
    Q->Length--;
    Q->A[Index] = Q->A[Q->Length];
    while (Index > 0) {
      size_t Child = (Index + 1)/ 2 - 1;
      if (Q->A[Index] >= Q->A[Child]) {
        break;
      }
      PriorityQueue_T tmp = Q->A[Index];
      Q->A[Index] = Q->A[Child];
      Q->A[Child] = tmp;
      Index = Child;
    }
  }
}

void PriorityQueue_Insert(PriorityQueue *Q, PriorityQueue_T x) {
   if (Q->Length < Q->Size || x > Q->A[0]) {
    if (Q->Length >= Q->Size) {
      PriorityQueue_Remove(Q);
    }
    size_t Index = Q->Length++;
    Q->A[Index] = x;
    while (Index > 0) {
      size_t Child = (Index + 1)/ 2 - 1;
      if (Q->A[Index] >= Q->A[Child]) {
        break;
      }
      PriorityQueue_T tmp = Q->A[Index];
      Q->A[Index] = Q->A[Child];
      Q->A[Child] = tmp;
      Index = Child;
    }
  }
}

// Pseudo code here to end
void PQ_FindNthSmallest(PriorityQueue_T Array[W][H], size_t N) {
  PriorityQueue Q;
  Q.Length = 0;
  Q.Size = N;
  Q.A = malloc(Q.Size * sizeof(PriorityQueue_T));

  For each element in the array
    PriorityQueue_Insert(&Q, Array[x][y]);

  printf("Nth smallest: %CorrespondingFormat", Q.A[0]);
  free(Q.A);
}