检查2d数组的所有元素是否相等的最快方法

时间:2017-05-31 19:54:50

标签: c++ arrays algorithm loops equality

我有一个二维数组houses[5][2] = {{1,1},{1,1},{1,1},{1,1},{1,1}} 检查该数组中所有元素是否相等的最快方法是什么? 这是我到目前为止所尝试的: ```

for(int j=0;j<5;j++){
 for(int k=0;k<6;k++){
   if(houses[j][k] == houses[j+1][k+1] && j+1 != 5 && k + 1 != 6)
     equal = true;
    else{
     equal = false;
     break;
     }
}
}

这不能比较所有元素,我知道如何比较所有这些元素,但它似乎是一个很长的循环..有更快的方法吗?

5 个答案:

答案 0 :(得分:3)

您当前的代码将失败,因为break只会让您退出一个循环。你必须退出两者,这需要第二次检查,如下所示:

auto the_value = houses[0][0];
bool equal     = true;

for(int j=0;j<5;j++){
  for(int k=0;k<6;k++){
    if(houses[j][k]!=the_value){
      equal = false;
      goto done;
    }
  }
  if(!equal)
    break
}

(将第一个元素存储在变量中,然后循环遍历所有元素以检查它们是否等于该变量,通过检查相邻元素来避免调用的混乱。)

同时打破两个循环需要黑暗艺术(goto),但如果你受到纪律处分可能会更加可读/可维护,并且可能会稍快一些,具体取决于你的编译器:

auto the_value = houses[0][0];
bool equal     = true;

for(int j=0;j<5;j++)
for(int k=0;k<6;k++)
  if(houses[j][k]!=the_value){
    equal = false;
    goto done; //Danger, Will Robinson!
  }

done:
//More stuff

您可能会发现平面阵列更快:

auto the_value = houses[0][0];
bool equal     = true;
for(int i=0;i<5*6;i++)
  if(houses[i]!=the_value){
    equal = false;
    break;
  }

2D数组作为1D连续数组存储在内存中。使用平面阵列寻址访问相同的内存位置,但显式避免强制内部算法。对于高性能代码,您可能希望默认使用平面数组。

由于您可能会多次使用此类函数或将其嵌入到其他复杂代码中,您可能希望将其抽象化:

template<class T>
bool AllEqual(const T& arr, size_t N){
  T the_value = arr[0];
  for(int i=0;i<N;i++)
    if(arr[i]!=the_value)
      return false;
  return true;
}

AllEqual(houses, 5*6);

由于您使用C ++进行编码,因此您可能不希望使用原始数组。让我们使用STL重写代码,假设是扁平数组:

template<class T>
bool AllEqual(const std::vector<T>& arr){
  return std::all_of(arr.begin(), arr.end(), [&](const T& x){ return x==arr[0]; });
}

std::vector<int> houses = {}; //Replace with appropriate initialization
if(AllEqual(houses))
  //Do stuff

(另外:正如另一位回答者提到的,你向数组中添加数据的方式似乎暗示它应该是2x6 / 6x2数组而不是5x6 / 6x5。)

答案 1 :(得分:2)

首先,您了解您的阵列是什么样的吗?您有两次6次,但您使用了background-image: url("/frame.jpg"); 。这是5行6列。你应该得到一个错误:

houses[5][6]

你真正想要的是6行和2列。

至于检查二维阵列的所有元素是否相等的方法,我会采用一种简单的方法;将数组的第一个元素存储到变量中,例如命名为main.cpp:5:55: error: excess elements in array initializer int houses[5][6] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1}}; ^~~~~ ,并检查该值与所有其他元素。如果它不等于只有一个元素,那么就足以做出决定并说并非所有元素都相等,如下例所示:

v
  

如果我使用1D模拟2D数组,它会更快吗?

我对此表示怀疑。他们的想法是内存位置是连续的,但这是在2D情况下最常发生的情况,因为行多于列。

这是我的实验:

#include <iostream>

bool allEqual(int arr[][2], int rows)
{
    int v = arr[0][0];
    for(int i = 0; i < rows; ++i)
        for(int j = 0; j < 2; ++j)
            if(v != arr[i][j])
                return false;
    return true;
}

int main(void)
{
    int houses[6][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1}};
    allEqual(houses, 6) ? std::cout << "All " : std::cout << "Not all ";
    std::cout << "elements are equal\n";
    return 0;
}

和我的代码,基于我的Time measurements (C++)

Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x -O3 -o 2d 2d.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./2d
2D array took 1.48e-10 seconds.
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x -O3 -o 1d 1d.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./1d
Emulating 2D array with 1D array took 1.5e-10 seconds.

其中2d.cpp是直截了当的方式。

使用此answer中提供的相等方法获取2D数组,报告的时序相似。

此外,还有std::equal,在性能方面与我上面的代码相当,报告的时间为:

#include <iostream>

#define ROWS 10000
#define COLS 20
#define REPEAT 1000

#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>

bool allEqual(int* arr, const int size)
{
    int v = arr[0];
    for(int i = 0; i < size; ++i)
        if(v != arr[i])
            return false;
    return true;
}

void fill(int* arr, const int size)
{
    for(int i = 0; i < size; ++i)
        arr[i] = 1;
}

int main(void)
{
    const int size = ROWS * COLS;
    int houses[size];
    fill(houses, size);

    bool equal;

    using namespace std::chrono;
    high_resolution_clock::time_point t1 = high_resolution_clock::now();
    for(int i = 0; i < REPEAT; ++i)
        equal = allEqual(houses, size);
    high_resolution_clock::time_point t2 = high_resolution_clock::now();
    duration<double> time_span = duration_cast<duration<double>>(t2 - t1);
    std::cout << "Emulating 2D array with 1D array took " << time_span.count()/(double)REPEAT << " seconds.\n";

    return 0;
}

它的复杂性是:“在first1和last1之间的距离上达到线性:比较元素直到找到不匹配。”

<强>摘要

std::equal with 2D array took 1.63e-10 seconds. 没问题,需要程序员减少工作量,因此可以使用它。

答案 2 :(得分:2)

多件事:

首先,正如其他人所指出的那样:

int houses[5][6] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1}};

错了,左侧声明了一个包含5行和6列的数组,但是右侧构成了一个包含6行和2列的数组。

在一般情况下,比较2d数组(或甚至是1d数组)的所有元素都在O(n)中,因为对于每个元素,您必须检查所有其他元素。您可以稍微优化它,但它仍然是O(n)算法。在最一般的情况下:

A[n][m] is an array of n rows and m columns

for(int i=0; i<n*m; i++)
{
   if(A[0][0] != A[i/n][i%n])
     return false;
}
return true;

这看起来有点令人困惑所以让我解释一下:

一个2d数组有n * m个元素,所以在一个循环中查看所有这些元素的简单方法是[i / n](如果我&lt; n,那么它是第一行,如果n&lt; i&lt; 2n然后它是第二行......)并且[i%n]给你余数。这样我们就可以在一个循环中迭代整个数组。

由于我们希望所有元素都相同,如果第一个元素与所有其他元素相同,那么它们将是相同的,如果至少on不同则它们不是全部相同。

答案 3 :(得分:1)

最快的方式:

int houses[6][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,2}};

int equals()
{
    int *p = (int *)houses;
    int *end = p + 6*2;
    int v = *p++;
    for(; p < end; p++)
        if (*p != v)
            return 0;
    return 1;
}

我写它是为了好玩,不要在生产中使用它。 相反,遍历它们全部:

int equals() {
   int v = houses[0][0];
   for(int j=0;j<5;j++)
      for(int k=0;k<6;k++)
         if (houses[i][j] != v)
            return false;
   return true;
}

答案 4 :(得分:0)

  

我们可以简单地检查该数组中的所有元素是否相等   或不。只需分配第一行&amp;变量中的列元素。然后比较每个元素。如果不相等则返回false。

代码段:

bool Equal(int **arr, int row, int col)
{
   int v = arr[0][0];
   for(int i=0; i<row; i++)
   {
      for(int k=0; k<col; k++)
      {
         if(arr[i][k]!=v)  return false;
      }
   }
   return true;
}
相关问题