打印唯一的行号。
以下是我的实施:
#include <iostream>
#include <cmath>
int rowsToInt(int m[][5], int row, int cloumLen) {
int sum = 0;
// m[row][column]
for (int i = 0; i < cloumLen; i++) {
sum += m[row][i]*(std::pow(2,i));
}
return sum;
}
void removeDuplicate(int m[][5], int row, int column) {
if (!m) {
return;
}
int tracker = 0;
int mask = 1;
int value;
for (int i = 0; i < row; i++) {
value = rowsToInt(m, i, column); // 3
if (((mask << (value - 1)) & tracker) == 0) {
// print unique row
std::cout << "row: " << i << " is unique" << std::endl;
// set that bit to 1
tracker = tracker ^ (mask << (value - 1));
}
}
}
int main() {
int array[5][5] = {
{0,1,0,0,1},
{1,0,1,1,0},
{0,1,0,0,1},
{1,1,1,0,0},
{1,1,0,1,1}
};
removeDuplicate(array, 5, 5);
return 0;
}
输出是:
row: 0 is unique
row: 1 is unique
row: 3 is unique
row: 4 is unique
运行时间是多少?我认为它的O(行*列);因为每行都会访问每个列元素。
这是最佳的运行时间吗?
答案 0 :(得分:2)
您的方法似乎有问题:
函数rowsToInt
将5 int
的子数组转换为0
和31
之间的值,假设这些值严格为二进制(0或1)。 / p>
在函数removeDuplicates
中,您将这些值用作表达式中的移位计数器:(mask << (value-1))
其中mask
是int
,其值为1
。这是一种精确的方式来跟踪到目前为止看到的行,但该表达式调用value == 0
的未定义行为。
您应该使用unsigned long
的{{1}}类型来解决此问题,保证至少有32位,tracker
已定义且值(1UL << value)
与0
不同}}
复杂度确实是 O(rows * cols),但算法固有地限于31
,因此当cols <= 5
无法增长时很难谈论复杂性任意。
此外,使用cols
计算二进制值的效率非常低。
这是一个更简单的版本:
pow(2, i)
答案 1 :(得分:1)
代码中最慢的部分是std::pow()
,对于有200000行的数组,它会被调用一百万次需要相当长的时间,所以不要在没有必要的情况下在循环中使用它。如果你需要2的幂,最快的方法是使用按位旋转,就像@chqrlie一样。一般来说,如果你需要N的权力,你可以得到如下:
int rowsToInt (bool m[][5], int row, int cloumLen) {
int sum = 0;
for (int i = 0, p = 1; i < cloumLen; i++) {
sum += m[row][i]*p;
p *= N;
}
return sum;
}
现在进行优化。如果您正在使用二进制矩阵,为什么使用整数?它需要4倍的RAM,因此请使用bool array[rows][cols]
。行数和列数是常量,因此不需要将它们传递给函数。您只需声明全局const int rows = 7, cols = 5
即可。还有一个更重要的因素。如果要在大矩阵中搜索唯一的二进制行,那么计算找到的二进制行是值得的。如果您已经找到了2 ^ cols,那就离开循环。
您的搜索方法相当复杂。让我展示两种更简单的方法来解决您的问题。
更紧凑的方式:
// the code inside removeDuplicate function
unsigned long tracker = 0; // now it looks like 32 zeros
for (int i = 0; i < row; ++i) {
int value = rowsToInt (m, i, column); // getting dec value
if (((tracker >> value) & 1) == 0) { // if the valueth bit is equal to zero
tracker |= (1UL << value); // set it equal to one
std::cout << "row: " << i << " is unique" << std::endl;
if (tracker = 0xffffffff) return; // if all bits are equal to 1, we've found all the unique rows
}
}
最简单的一个:
// the code inside removeDuplicate function
bool found[32] = {false}; // using array instead of UL
int counter = 0; // and simple counter of unique rows
for (int i = 0; i < row; i++) {
int value = rowsToInt (m, i, column); // getting dec value
if (!found[value]) { // if the valueth element is equal to zero
found[value] = true; // set it equal to one
++counter; // and increase the counter
std::cout << "row: " << i << " is unique" << std::endl;
if (counter == 32) return;
}
}