将行和列排序的二维数组转换为已排序的一维数组

时间:2012-09-18 19:07:11

标签: algorithm matrix array-algorithms

给出n * n个元素的二维数组:

  • 所有行都已排序
  • 所有列都已排序

例如:

1 5 7
2 6 8
3 9 10

将其转换为1-D排序数组。是否有比O(nlog(n))更好的解决方案。

6 个答案:

答案 0 :(得分:1)

它的复杂程度可能低于n^2,因为您有n^2个元素,您必须至少每次检查一次。

执行此操作的算法是标准k-way合并,其复杂度为N log k,其中N是要合并的项目总数,k为序列数。

n*n数组中,您要合并n*n项和n个序列(即行)。所以,用上面的等式代替:

N log k
N = (n*n)
k = n
(n*n) log n

将2D数组转换为已排序的1D数组n^2 log n

答案 1 :(得分:0)

您可以使用函数f(x,y)=(f(x),f(y))来降低复杂性并使2d数组变平。它还重新排序1d阵列。既然它是一个函数,它更像是一个散列算法,也许不是你想要的东西?

答案 2 :(得分:0)

你应该发布你的O(n log n)解决方案:事实是,没有真正可行的解决方案。这就是原因。您有n*n个元素。因此,您必须做的最好的事情是n^2,因为您必须至少访问一次每个元素。考虑一下。您必须填充长度为n*n的1-D数组(即2-D数组的每个元素必须存在于新的1-D数组中)。因此,您无法在O(n log n)中解决此问题。

答案 3 :(得分:0)

我有时间:O(n * n log(2n))空间O(2n)算法。

基本思路如下

a [0] [0]肯定是最小的元素。因为元素是行方式和列方式排序的,所以下一个最小元素将是min(a [0] [1],a [1] [0])。比如,[0] [1]是两者中最小的,下一个候选者将是min(a [0] [2],a [1] [1],a [1] [0])

等等,

<强> ALGO:

选择最小的候选元素,打印出来。将元素推到最小元素的右侧和底部作为潜在候选者。 (检查出来或绑定。)   这样做直到不再存在候选元素。

需要DS:

候选元素可以使用堆维护(top是min元素)但是你需要确保你不要将同一个元素推两次。 (y可以是x的右边和z的底部)。   在你推送堆之前你需要知道元素是否已被推送。

这两个要求都由set(有序)(我用c ++编写代码)

优雅地处理

在集合中存储索引将允许我轻松地将下一个候选元素推送到候选Ds   在我的候选人ds中,我在任何时间点都保持不超过n + n个元素   以下是我使用的比较功能。

bool operator()(const int& a,const int& b) const{
        int ai=a/m,aj=a%m;
        int bi=b/m,bj=b%m;
        if(input[ai][aj]!=input[bi][bj])
        return input[ai][aj]<input[bi][bj];
        else
        return a<b;
    }

示例实现位于:http://ideone.com/w208Af

答案 4 :(得分:0)

你可以在O(n)中做到这一点。我不同意这是不可能比n ^ 2更快,因为在这种情况下n * n = n因为当你谈论时间复杂性时你指的是列表中的元素数量。这是O(n)解,其中n = min-max。为此,您需要知道列表中可能包含的最小数字和最大数字。你不需要知道它们是最低和最高的。

    int[] Sorted1dArray(int[][] arr, int min, int max)//basically counting sort
    {
       int index = 0;
       int rowColSize = arr[0].Length;
       int[] newArr = new int[max-min];
       int[] ret = new int[rowColSize *rowColSize ];
       for(int i=0;i<rowColSize ;i++)//
       {
          for(int j=0;j<rowColSize ;j++)
             newArr[arr[i][j]]++;
       }
       for(int i=0;i<newArr.Length;i++)
       {
          for(int j=0;j<newArr[i];j++)
          {
             ret[index++]=newArr[j];
          }
       }
       return ret;
    }

答案 5 :(得分:0)

我认为这将是我采取的方法:

1)从第一行开始 - “1 5 7”。我们知道在开始时,行是排序的,因此我们保证最左边的元素是最少的,不需要比较。输出1,然后将第一列向上移动,给我们“2 5 7”。

2)现在比较前两个元素。只要第一个元素小于第二个元素,就保持输出第一个元素并将其各自的列向上移动。这给了我们输出 2和3的结果数组为“5 7”(因为第一列现在为空)。

3)继续对剩余的两个colums做同样的事情。在我们遇到第一个不同的情况之前,这将给出5和6的输出 - 此时我们的数组将包含“9 7”。

4)在这种情况下,我们将从最后一列输出值并将其向上移动,在输出7后给出“9 8”。我们再次得到第一个元素更大的情况,所以我们'输出第二个并将该列向上移动,留下“9 10”。

没有彻底分析它,但我认为这是O(N),因为你可以对各个列之间的关系做出假设,因此最多有N个比较。