给定一个整数n,用n个内部节点枚举所有可能的完整二叉树。(完整的二叉树在每个内部节点上恰好有2个子节点)。树结构应作为树的预遍历输出,其中1表示内部节点,0表示外部节点(空)。
以下是前n个示例:
0:
0
1:
100
2:
11000
10100
3:
1110000
1101000
1100100
1011000
1010100
这是一场代码高尔夫,奖金最少的人物。这些树应该每行输出到stdout。该程序应从命令行或标准输入中读取n。
给定一个整数n,用n个内部节点枚举所有可能的完整二叉树。(完整的二叉树在每个内部节点上恰好有2个子节点)。树结构应作为树的预遍历输出,其中1表示内部节点,0表示外部节点(空)。
以下是前n个示例:
0:
0
1:
100
2:
11000
10100
3:
1110000
1101000
1100100
1011000
1010100
这是一场代码高尔夫,奖金最少的人物。这些树应该每行输出到stdout。该程序应从命令行或标准输入中读取n。
Answers:
Count包含4个字符,用于“ -ln
”选项。从标准输入中取n。
新的建设性方法:
@a=0;map{%a=();map{$a{"$`100$'"}=1while/0/g;}@a;@a=keys%a}1..$_;print for@a
通过依次为每个树(n-1)中的每个叶子(“ 0”)替换一个新的内部节点(“ 100”)来形成n的解决方案。
(我将此概念归功于其他解决方案,这些解决方案使用内部节点进行[100-> 0]替换来验证顺序生成的字符串,并且我相信-在基于该概念编写答案之后,我看到了同样的0-在某人的中间编辑中> 100种构建方法。)
先前的递归方法:
sub t{my$n=shift;if($n){--$n;for$R(0..$n){for$r(t($R)){for$l(t($n-$R)){push@_,"1$l$r"}}}}else{push@_,"0"}@_}print for t$_
递归的:
sub tree {
my ($n) = @_;
my @result = ();
if ( $n ) {
for $right_count ( 0 .. $n-1 ) {
for $right ( tree( $right_count ) ) {
for $left ( tree( ($n-1) - $right_count ) ) {
push @result, "1$left$right";
}
}
}
}
else {
push @result, "0";
}
return @result;
}
foreach $tree ( tree($_) ) {
print $tree;
}
从命令行运行,即“ php golf.php 1”输出“ 100”。
编辑:用替代方法剪切4个字符,从0而不是从$ n递归建立字符串。对缩短的三元运算符使用PHP 5.3;否则,还需要2个字符。
编辑2:在循环中进行了一些更改后,又保存了4个字符。
编辑3:我正在尝试一种不同的方法,终于在旧方法之下得到了它。
所有树都可以视为4 ^ n(或n,当n = 0时为0)和2 * 4 ^ n之间的整数的二进制表示。此函数循环遍历该范围,并获取每个数字的二进制字符串,然后通过将“ 100”替换为“ 0”来重复减少它。如果最后一个字符串为“ 0”,则它是一棵有效的树,因此将其输出。
for($i=$p=pow(4,$argv[1])-1;$i<=2*$p;){$s=$d=decbin($i++);while($o!=$s=str_replace(100,0,$o=$s));echo$s?:"$d\n";}
(n=4**gets.to_i).times{|i|s=(n+i-1).to_s 2;t=s*1;0while s.sub!'100',?0;puts t if s==?0}
输入是从stdin中读取的。
> echo 2 | ruby binary_trees.rb
10100
11000
编辑1:更改了IO(请参阅Lowjacker的评论)
b=->n{n==0?[?0]:(k=[];n.times{|z|b[z].product(b[n-1-z]){|l|k<<=?1+l*''}};k)}
puts b[gets.to_i]
编辑2:更改算法。
b=->n{n==0?[?0]:(k=[];b[n-1].map{|s|s.gsub(/0/){k<<=$`+'100'+$'}};k.uniq)}
puts b[gets.to_i]
编辑3:该版本现在采用第三种方法(使用migimaru的思想)。
编辑4:再次两个字符。谢谢migimaru。
*?\n
,因为会puts
在自己的行中打印数组的每个元素。
main=do n<-readLn;mapM putStrLn$g n n
g 0 0=[['0']]
g u r|r<u||u<0=[]
g u r=do s<-[1,0];map((toEnum$s+48):)$g(u-s)(r-1+s)
由于IO是haskell中代码的重要部分,因此也许有人可以使用另一种语言使用类似的解决方案。本质上,如果对角线交叉,则随机从左下角到右上角走一个正方形。等效于以下内容:
module BinTreeEnum where
import Data.List
import Data.Monoid
data TStruct = NonEmpty | Empty deriving (Enum, Show)
type TreeDef = [TStruct]
printTStruct :: TStruct -> Char
printTStruct NonEmpty = '1'
printTStruct Empty = '0'
printTreeDef :: TreeDef -> String
printTreeDef = map printTStruct
enumBinTrees :: Int -> [TreeDef]
enumBinTrees n = enumBinTrees' n n where
enumBinTrees' ups rights | rights < ups = mempty
enumBinTrees' 0 rights = return (replicate (rights+1) Empty)
enumBinTrees' ups rights = do
step <- enumFrom (toEnum 0)
let suffixes =
case step of
NonEmpty -> enumBinTrees' (ups - 1) rights
Empty -> enumBinTrees' ups (rights - 1)
suffix <- suffixes
return (step:suffix)
mainExample = do
print $ map printTreeDef $ enumBinTrees 4
~[1,]\,{;{[:l.,,]zip{({;}{~:a;[l a<~1 0.l a)>~]}if}/}%}/{n}%
如果有人对此感兴趣,我为Emacs 构建了golfscript模式。