我有一个二维数组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;
}
}
}
这不能比较所有元素,我知道如何比较所有这些元素,但它似乎是一个很长的循环..有更快的方法吗?
答案 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;
}