用二进制数填充数组

时间:2010-05-08 21:21:04

标签: algorithm

首先,这不是作业!

我的问题来自Robert Sedgewick的书中的 C ++第三版算法

给出了一个大小为n乘2 ^ n(二维)的数组,我们应该用二进制数大小的n来填充它。例如,对于n = 5,结果将是:

00001
00010
00011
00100
00101
00110
00111    

等等。我们应该将这个位序列放入数组中。

7 个答案:

答案 0 :(得分:1)

我不太了解C / C ++,但是一种天真的,与语言无关的方法是简单地找到A [i,j]的公式,其中i \ in [0,2 ^ n - 1]和j \ [0,n-1]。

在单词中,A [i,j]包含i的第j个二进制数字,从最高位开始计数。

在公式中,A [i,j] =(i AND 2 ^(n-1-j))SHR(n-1-j)

其中AND是二进制按位和运算符,SHR是二进制“shift bits right”运算符。 a ^ b意味着(当然)“提升到b的力量”。

丑陋的概念验证德尔福代码:

var
  i: Integer;
  twoton: integer;
  j: Integer;
begin
  twoton := round(IntPower(2, n));
  SetLength(A, twoton, n);
  for i := 0 to twoton - 1 do
    for j := 0 to n - 1 do
      A[i, j] := (i and round(IntPower(2, n-1-j))) shr (n-1-j);

这很好用,但我确信有更快的方法......至少有一个可以在数组中存储2的幂并使用POWEROF2 [k]而不是round(IntPower(2,k)),但是 - 当然 - 这取决于你的语言。毕竟,IntPower是Delphi的功能。

如何运作

假设我们有数字23,或者,在二进制10111中。现在我们想要第三个二进制数字。然后我们想要数字10111和数字00100,如果搜索到的数字是1则获得00100,否则获得00000。请注意,00100,我们与之对的数字,只是十进制的2 ^ 3;因此所有的权力都是2。现在我们有数字00N00,其中N是被寻找的数字,在这个例子中是1:00100。我们现在将这个数字的3位向右移位(SHR操作),以获得00001 = 1,并且 - il! - 我们已经得到了我们的数字!

更智能的方法

我不知道C如何存储数组,但你可以简单地创建一个无符号整数的2 ^ N维向量 A(8位,16位或32位,最好是),即数字0,1,2,...,2 ^ N - 1,然后认为这实际上二维矩阵。实际上,如果我们将UNSINGED_INTEGER [k]表示为UNSIGNED_INTEGER的第k位,那么A [i] [k]或多或少是你想要的矩阵......

答案 1 :(得分:1)

每个数字比二进制数系统中的最后一个数字多一个。

以二进制

递增(加1)
  • 从数字的右端开始
  • 将所有尾随的(如果有的话)转换为零
  • 将最后的0变为1
  • 如果字符串中没有0,那就太过分了。

请注意,<<运算符将左操作数乘以2乘以右操作数的幂。数字1l只是1表示为long,在64位系统上为64位。

template< size_t n > // template detects size of array. Strictly optional.
void ascending_binary_fill( bool (&arr)[ 1l << n ][ n ] ) {
    std::fill( arr[0], arr[0] + n, 0 ); // first # is 0
    for ( size_t pred = 0; pred < 1l << n; ++ pred ) {
        int bit = n; // pred = index of preceding number; bit = bit index
        while ( arr[ pred ][ -- bit ] ) { // trailing 1's in preceding #
            arr[ pred+1 ][ bit ] = 0; // ... are trailing 0's in current #
        }
        arr[ pred+1 ][ bit ] = 1;
        std::copy( arr[ pred ], arr[ pred ] + bit, arr[ pred+1 ] );
    }
}

答案 2 :(得分:1)

非常简单!

这是伪代码的解决方案

assert(bits <= 32)
int array[pow(2, bits)] 
for (uint i= 0; i < length(array); i++)
    array[i]= i;

结果是一个数组,其中填充了您作为示例提供的模式

答案 3 :(得分:1)

public static uint[][] FillUpCode(uint qValue, uint kValue)
    {
        var size = (ulong)Math.Pow(qValue, kValue);
        var array = new uint[size][];

        var workArray = new uint[kValue];
        long position = kValue - 1;
        ulong n = 0;

        while (position > 0)
        {
            while (workArray[position] < qValue)
            {
                var tempArray = new uint[kValue];
                Array.Copy(workArray, tempArray, kValue);
                array[n++] = tempArray;
                workArray[position]++;
            }

            while (position > 0)
            {
                workArray[position] = 0;
                if (workArray[position - 1] < (qValue - 1))
                {
                    workArray[position - 1]++;
                    position = kValue - 1;
                    break;
                }
                position--;
            }
        }
        return array;
    }


qValue - 数字基数,kValue - 行长度:)当您需要以不同的数字生成数组时,代码可能很有用。

答案 4 :(得分:0)

所以基本上,你需要一个从零开始的数组,并且最多可以达到2 ^ n? Psuedo-C:

bool[][] Fill(int n) {
   max = Pow(2, n);
   array = new bool[max, n];

   for i from 0 to max - 1
      for j from 0 to n - 1
         array[i][n - j - 1] = ((i >> j) & 1) == 1;
   return array;
}

我能看到的唯一问题是它的上限是n = 32,但是这已经占用了大量的内存,所以这真的不是问题。
请注意,你也可以使它成为一维数字并用0到2 ^ n的数字填充它,并且实际上将使用(A [i]&gt;&gt; j来检索A [i] [j] th元素)&amp; 1。

答案 5 :(得分:0)

这是一个非常基本的问题,我将使用这个Java代码演示:

public class Bin {                                                  // prints:   
   static String zero(int L) {                                      // 0000
      return (L <= 0 ? "" : String.format("%0" + L + "d", 0));      // 0001
   }                                                                // 0010
   static String zeroPad(String s, int L) {                         // 0011
      return zero(L - s.length()) + s;                              // 0100
   }                                                                // 0101
   public static void main(String[] args) {                         // 0110
      final int N = 4;                                              // 0111
      for (int i = 0; i < (1 << N); i++) {                          // 1000
         System.out.println(zeroPad(Integer.toBinaryString(i), N)); // 1001
      }                                                             // 1010
   }                                                                // 1011
}                                                                   // 1100
                                                                    // 1101
                                                                    // 1110
                                                                    // 1111

我将留待您了解如何实施toBinaryString以及如何使用位填充int[][]

答案 6 :(得分:0)

// My solution is based on that of Potatoswatter.

// use cols value where rows = 2^cols
// start here after setting cols
rows = pow(2.0, double(cols));

// memory allocation
bool **array = new bool*[rows];
for (int i = 0; i < rows; i++) {
    array[i] = new bool[cols];
}

std::fill( array[0], array[0] + cols, 0 ); // maybe not needed

for (int i = 1; i < rows; i++) { // first row is zero, start at second 
    // starting at right ...
    int j = lits - 1;
    // turn the last zero into a one
    if (array[i][j] == false) {
        array[i][j] = true;
    }
    else {
        // turn all trailing ones into zeros (prior to first zero)
        while (array[i][j] == true) {
            array[i][j] = false;
            j--;
        }
        array[i][j] = true;
    }
    // copy this row to next row
    if (i < (rows - 1)) {
        std::copy(array[i], array[i] + lits, array[i+1]);
    }
}
相关问题