在二进制 2D 数组中查找唯一行
Find the unique rows in Binary 2D array
打印唯一的行号。
以下是我的实现:
#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(行*列(;因为每一行然后访问每个列元素。
这是最佳运行时间吗?
您的方法似乎有问题:
-
函数
rowsToInt
将 5int
的子数组转换为介于0
和31
之间的值,假设这些值是严格的二进制(0 或 1(。 -
在函数
removeDuplicates
中,您可以将这些值用作表达式中的移位计数器:(mask << (value-1))
其中mask
是值为1
的int
。这是跟踪到目前为止看到的行的精明方法,但表达式会调用value == 0
的未定义行为。
您应该使用unsigned long
类型来解决此问题 tracker
,保证至少有 32 位,并且对于0
31
的值(1UL << value)
定义和不同。
复杂度确实是O(rows * cols(,但算法本质上仅限于cols <= 5
,所以当cols
不能任意增长时,很难谈论复杂度。
此外,使用 pow(2, i)
计算二进制值的效率非常低。
这是一个更简单的版本:
#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] << i;
}
return sum;
}
void removeDuplicate(int m[][5], int row, int column) {
if (!m) {
return;
}
unsigned long tracker = 0;
for (int i = 0; i < row; i++) {
int value = rowsToInt(m, i, column); // 3
if (((1UL << value) & tracker) == 0) {
// print unique row
std::cout << "row: " << i << " is unique" << std::endl;
// set that bit to 1
tracker |= 1UL << value;
}
}
}
int main() {
int array[7][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},
{0,0,0,0,0},
{0,0,0,0,0},
};
removeDuplicate(array, 7, 5);
return 0;
}
代码中最慢的部分是 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;
}
现在进行优化。如果您使用的是二进制矩阵,为什么要使用整数 1?它需要 4 倍的 RAM,因此请使用 bool array[rows][cols]
.行数和列数是常量,因此无需将它们传递给函数。您可以只声明全局const int rows = 7, cols = 5
。还有一个重要因素。如果您正在大矩阵中搜索唯一的二进制行,则值得计算找到的二进制行。如果您已经找到了其中的 2^col,请离开循环。
您的搜索方法相当复杂。让我展示两种更简单的方法来解决您的问题。
更紧凑的方式:
// 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;
}
}
- 在子数组中查找多个查询的不同(唯一)值的数量
- 为什么我的 Rcpp 实现查找唯一项的数量比基本 R 慢?
- 如何在给定任意数量的整数的情况下创建一个唯一键?并使用该键存储,然后从地图中查找
- 尝试查找数组中唯一值的数量,但它始终等于 0
- 快速的唯一组合(来自重复项列表),无需查找
- 使用哈希 C++ 查找具有 k 个不同/唯一字符的最长子字符串
- 我的递归算法中的问题,用于查找所有最短、唯一的路径
- 提升 BGL BFS 查找从源到目标的所有唯一路径
- 使用笛卡尔产品查找唯一BST数量的直觉
- 查找具有唯一标签的前 K 元素的算法
- 查找参数包的唯一值的数目
- 在c++中查找数组中和等于零的所有唯一三元组
- 在 2D 标准::矢量<矢量中查找唯一值的有效方法<double>>
- 函数来查找树是否为mono(所有元素都是唯一的)
- 如何使用std::find查找唯一的数字
- [唯一相等运算符]在集合中查找重复元素并将其分组的快速算法是什么
- 在布尔矩阵中查找唯一的行(帮助解析std::string的垃圾输出)
- 查找所有唯一二叉搜索树的算法的时间复杂度是多少?
- 非唯一名称空间限定查找的代码示例
- 在数组中查找唯一的数字