【问题标题】:Find the unique rows in Binary 2D array查找二进制二维数组中的唯一行
【发布时间】:2016-07-24 20:42:20
【问题描述】:

打印唯一的行号。

以下是我的实现:

#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(row*column);因为每一行然后每一列元素都会被访问。

这是最佳的运行时间吗?

【问题讨论】:

标签: c++ arrays matrix multidimensional-array


【解决方案1】:

你的方法好像有问题:

  • 函数rowsToInt 将5 个int 的子数组转换为介于031 之间的值,假设这些值是严格的二进制(0 或1)。

  • 在函数removeDuplicates 中,您将这些值用作表达式中的移位计数器:(mask &lt;&lt; (value-1)) 其中mask 是一个int,其值为1。这是一种跟踪目前看到的行的精明方法,但该表达式会调用 value == 0 的未定义行为。

您应该使用trackerunsigned long 类型来解决此问题,保证至少有32 位,并为031 定义和不同的值(1UL &lt;&lt; value)

复杂度确实是O(rows * cols),但是算法天生就局限在cols &lt;= 5,所以cols不能任意增长的情况下很难谈复杂度。 p>

此外,使用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;
}

【讨论】:

    【解决方案2】:

    您的代码中最慢的部分是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^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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-03
      • 1970-01-01
      • 2023-01-24
      • 1970-01-01
      • 2011-01-31
      相关资源
      最近更新 更多