假设我们有一个像这样的树结构:
这由15个节点组成,可以大于或小于此节点。但是顺序是精确的,树给节点从左到右,从上到下的顺序号。
问题是:如何区分节点在左子树(2-4-5-8-9-10-。)还是右子树(3-6-7-12- ...)。
我期望的是,找到一个数学公式或编码算法,向我显示子节点所在的子树。只有输入/值是元素的订单号。
答案 0 :(得分:1)
假设您的电话号码为N。
您可以通过R = floor(log 2 (N))(从0开始)来找到N行。
该行的第一个和最后一个数字分别是2 R 和2 R + 1 -1。因此,您只需要找出N靠近哪个端点即可。
具体来说,N在左侧子树iff中:
N-2 R <2 R + 1 -1-N
重新排列和替换:
N <(3 * 2 floor(log 2 (N))-1)/ 2
使用Python 3进行完整性检查(True
表示左侧子树; False
表示右侧):
>>> from math import floor, log2
>>> for N in range(1,16):
... print(N, N < (3*2**floor(log2(N)) - 1)/2)
...
1 False
2 True
3 False
4 True
5 True
6 False
7 False
8 True
9 True
10 True
11 True
12 False
13 False
14 False
15 False
答案 1 :(得分:1)
@arshajii的答案起作用了,尽管我认为1
不应被视为在左子树中。使用标准数学函数,该答案也是一个很好的“数学公式”。但是,对于仅涉及整数的问题,该答案使用浮点运算。这是解决问题的另一种方法。
如果您查看树中数字的二进制展开,您将看到左子树中的数字在第二高有效位中有一个0
位,而在树中的数字右子树在第二个最高有效位中具有一个1
位。检查该位是容易且快速的,尽管在不同的编程语言中,如何执行的操作也有所不同。
以下是在Python 3中执行此操作的两种方法:
not (n & (1 << n.bit_length() - 2))
或
bin(n)[3]=='0'
要检查正确的子树,请从第一种方法中删除not
或在第二种方法中将0
更改为1
。
在我的系统上,@ arshajii的答案需要1.34毫秒才能工作(使用%timeit
检查)。我的第一种方法需要260微秒,而第二种方法则需要257微秒。因此,我的任何一种方法都比@arshajii的代码快五倍以上。对我的代码进行类似的检查是
for n in range(2,16):
print(bin(n)[3]== '0')
和产量
True
False
True
True
False
False
True
True
True
True
False
False
False
False