【问题标题】:Gray Code Generation - n-bit Gray Codes格雷码生成 - n 位格雷码
【发布时间】:2018-09-16 00:09:21
【问题描述】:

这个问题是由hackerrank提出的,我得到了解决方案,但是在最后的测试用例中解决方案存在问题。

问题如下。

1 <= $n <= 65

以下是 1 位序列 (n = 1)

0 1

输出

1

下面是 2 位序列(n = 2)

00 01 11 10

输出

11 10

以下是 3 位序列(n = 3)

000 001 011 010 110 111 101 100

输出

111 101 100

以下是 4 位序列(n = 4)

 0000 0001 0011 0010 0110 0111 0101 0100 1100 1101 1111 
  1110 1010 1011 1001 1000

输出

1010 1011 1001 1000

解决方案示例

以下是从2位格雷码列表生成3位格雷码列表的步骤。

  • L1 = {00, 01, 11, 10}(2 位格雷码列表)
  • L2 = {10, 11, 01, 00}(L1 的反转)
  • 在 L1 的所有条目前加上“0”,L1 变为 {000, 001, 011, 010}
  • 在 L2 的所有条目前加上“1”,L2 变为 {110, 111, 101, 100}
  • 连接 L1 和 L2,我们得到 {000, 001, 011, 010, 110, 111, 101, 100}

下面给出第一个解决方案。(基于上面的解决方案示例)

但是下面给出的解决方案在 22,23 个数字之后将不起作用。 发生内存分配错误。

<?php

$input = 2;

$list_array = ["0","1"];
$reverse_array = array_reverse($list_array);

for($i = 1; $i < $input; $i++ )
{
    for($j = 0; $j < sizeof($list_array); $j++)
    {
        $list_array[$j] = "0".$list_array[$j];
    }

    for($k = 0; $k < sizeof($reverse_array); $k++)
    {
        $reverse_array[$k] = "1".$reverse_array[$k];
    }

    $list_array = array_merge($list_array,$reverse_array);
    $reverse_array = array_reverse($list_array);
}

for($l = sizeof($list_array) - $input; $l < sizeof($list_array); $l++)  
{
    print_r($list_array[$l]);
    echo "<br />";
}

?>

下面给出第二种解决方案

此解决方案将在 63 之前有效。在 63 之后,这将显示超时错误。

当 64 位 php 在 64 位操作系统上运行时,这将一直工作到 63 岁。如果是在64位操作系统上运行的32位php,31之后就不行了。

<?php

    $n = 59;

    $intial = pow(2, $n) - $n;

    $length = pow(2, $n) - 1;

    for($i= $intial; $i <= $length; $i++)
    {
        $decimal = ($i >> 1) ^ $i;
        print_r(decbin($decimal));
        echo "<br />";
    }
?>

请帮助我找到此解决方案。

问题:如何解决上面包括$n = 64 和$n = 65

参考:https://www.geeksforgeeks.org/given-a-number-n-generate-bit-patterns-from-0-to-2n-1-so-that-successive-patterns-differ-by-one-bit/

【问题讨论】:

  • 哪里有问题?你在解决什么问题?这些“输出”是什么意思?
  • 我认为上面已经详细解释过,n位的输出是最后n位。
  • 所以你想输出 2^64 个项目?
  • 是的。 @MBo 寻求更好的解决方案,而不是制作 2 ^ 64,请告诉我。
  • @MBo 我相信他只想要最后一个$n$n 位格雷码,所以对于$n = 65,即使有2^65 格雷码,也应该有65 行输出。

标签: php algorithm gray-code


【解决方案1】:

这应该适合你:

<?php

print_r( getResult( 4 ) );

function getResult ( $n ) {
    $result = [];
    for ( $i = 0; $i < $n; $i++ ) {
        $result[] = arr_xor(
          str_split( str_pad( str_pad( strtr( decbin($n - $i - 1), '01', '10' ), (int)ceil(log($n - $i - 1, 2)), '0', STR_PAD_LEFT ), $n, '1', STR_PAD_LEFT ) ),
          str_split( '0' . str_pad( substr( str_pad( strtr( decbin($n - $i - 1), '01', '10' ), (int)ceil(log($n - $i - 1, 2)), '0', STR_PAD_LEFT ), -1-(int)ceil(log($n - $i - 1, 2)), -1), $n - 1, '1', STR_PAD_LEFT ) )
        );
    }
    return $result;
}

function arr_xor( $a, $b ) {
    $result = [];
    for ( $i = 0; $i < count( $a ); $i++ )
        $result[] = (int)$a[$i] ^ (int)$b[$i];
    return implode( '', $result );
}

它仅使用您的第二个解决方案 (($i &gt;&gt; 1) ^ $i) 中的公式,但由于您不能将其用于大于 PHP_INT_MAX 的整数,因此它使用一个数组,每个元素代表一位。这不是最有效的解决方案,但可以轻松超过 65。$n = 1000 似乎没有问题。

【讨论】:

  • 能否解释一下getResult()函数内部2个参数的处理过程?
  • @JeesKDenny 第一个参数是一个包含2**n-n+i 位的数组,第二个参数是一个包含(2**n-n+i) &gt;&gt; 1 位的数组。有更简单的方法可以为 MAX_INT_SIZE 下的整数生成这些数组,但由于我希望它在 6432 以上工作,所以我使用了字符串操作。
  • @JeesKDenny 你可能最好只使用php.net/manual/en/function.gmp-xor.php 之类的东西,并且可以使用它比使用数组的答案更进一步,但我不想使用它因为它假定您已经拥有 gmp 扩展名,或者愿意并且能够编译并包含它。
  • 我已经浏览了这个库。但我很感兴趣不使用任何图书馆。感谢您的澄清。让我通过它。 @Paulpro
【解决方案2】:

另一个答案,它类似于@paulpro,这与我在第二个解决方案中应用的想法相同。 ($i &gt;&gt; 1) ^ $i

<?php

$n = 65;

for ( $i = 0; $i < $n; $i++ ) 
{
    $decimal = decbin($n - $i - 1);

    $replace = strtr( $decimal, '01', '10' );

    $cast = (int)ceil(log($n - $i - 1, 2));

    $padding = str_pad( $replace , $cast , '0', STR_PAD_LEFT );

    $a_string = str_pad( $padding, $n, '1', STR_PAD_LEFT );

    //shifting the bit to right
    $substring = substr( $a_string , 0 , -1);
    $b_string = str_pad( $substring , $n, '0', STR_PAD_LEFT );

    $a = str_split( $a_string );
    $b = str_split( $b_string );

    for ( $j = 0; $j < count( $a ); $j++ )
    {
        print_r((int)$a[$j] ^ (int)$b[$j]);
    }

    echo "\n";
}

?>

【讨论】:

    猜你喜欢
    • 2017-01-12
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 2010-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多