优化阵列处理循环

时间:2011-01-09 05:56:30

标签: c algorithm

我正在编写一个编程难题,我有点困惑。问题是计算二维平面上的磁盘交叉点的数量。 x始终为0,y是数组的索引。半径是元素存储在数组元素中。性能很好,元素数量少,元素少,但有大量元素,如10,000,000性能差。我目前正在使用2个嵌套for循环来处理数组。

感谢有人给予的任何帮助。我与给予我的数据结构联系在一起,无法改变它们。由于我处理整数而中心点位于同一y轴上,因此磁盘与另一个磁盘相交的计算。

以下是代码:

int number_of_intersections ( int A[], int n ) 
{
 int base = 0;
 int inc = 0;
 int intersect = 0;
 int maxrad = 0;
 int x;

 if (n>1)
 { 
  for (base=0;base<(n-1);base++)
  {
   inc = base+1;
   do
   { 
    if ( inc - base <= (A[base] + A[inc]))  
    {                                    
     intersect ++;
     if (!(intersect^10000000))   
     {
      return -1;
     }
    }
    inc ++;
   } while (inc < n);
  }
 }

 return intersect;
}

感谢您的时间

3 个答案:

答案 0 :(得分:4)

你的代码闻起来像是过早优化。

去除外部if语句,因为它无论如何都不会帮助你(外部循环不会在n&lt; = 1时执行)。

删除那里的魔法常数(10000000)和(我猜)比特诡计。它很难阅读,根本不灵活(至少应该是一个常量变量),并且使用 xor 代替 == 来表达逻辑。

也许用更易于阅读的for循环来交换你的do-while循环。 (由@Philip Potter建议)

现在你的代码看起来更清晰而不慢。也许你意识到现在你已经保存了一些代码行和一些括号,你可能会删除更多。

现在有了可读代码,您终于可以使用之前隐藏的更大优化了 - 请参阅其他帖子。

注意:不要提前做聪明的优化技巧。他们不会任何好。

编辑:明确要点; - )

int number_of_intersections (int A[], int n) 
{
     int intersect = 0;
     const int maxIntersections = 10000000;    

     for (int base = 0; base <  n-1; base++)
     {
        for(int inc = base+1; inc < n; inc++)
        { 
           if (inc - base <= A[base] + A[inc])  
           {                                    
              intersect ++;
              if (intersect == maxIntersections) return -1;
           }
        }
     }

     return intersect;
}

答案 1 :(得分:2)

你的方法是O(n ^ 2),因为你正在测试每对光盘,因此大量光盘的速度很快。

我无法想到一种方法可以让渐近更好的表现,但是你可以进行一项优化。

说你在元素p,它有半径m。显然,位于p-m <= y <= p + m的每个盘的中心在y = m时被盘覆盖。因此,您只需要为距离更远的光盘做任何工作。

答案 2 :(得分:0)

正如评论中所指出的,这实际上是一维问题。实际上,这是一个交叉区间的问题,其中区间[x,y]对应于盘中的最低和最高x坐标x =中心 - 半径和y =中心+半径。

考虑从左到右沿x和y点移动。您可以通过保留两个指向磁盘的指针进行排序,一个用于x点,另一个用于y点。使用数据结构来跟踪当前指针下的磁盘。当您看到x点时,识别位点磁盘和所有当前磁盘之间的交叉点,然后将其设置为当前磁盘。当您看到y点时,从当前磁盘中删除该点的磁盘。