问题是,给定BST,找出是否有两个数字加起来给定的数字k
。不应使用额外的内存。
现在如果它是一个排序数组,我可以简单地保留两个指针,一个在开头,一个在结尾。在每一步,我将计算指针指向的两个数字的总和,如果总和小于k,我会增加起始指针,否则减少结束指针,直到匹配,或指针重叠。 / p>
我可以用BST做同样的事情,通过inorder遍历将它转换为有序数组,但这需要额外的内存。所以我认为迭代器解决方案是有序的。我会保留两个迭代器,一个将以正常的顺序遍历BST,调用哪个将返回下一个更大的数字,另一个将以反向顺序遍历BST,每次调用时返回下一个较小的数字。
知道如何设计这样的迭代器吗?我更喜欢Python / Javascript中的解决方案。虽然Python提供了像iter
这样的函数,但我想用闭包来设计它。
答案 0 :(得分:3)
这种迭代器(使用闭包)在python中称为生成器。
生成器是函数,使用'yield'关键字而不是'return'。遇到yield时,返回相应的值,但函数的执行状态将被暂停,直到需要下一个值。
所以,你可以使用'yield'而不是'return'来实现树遍历功能,你的目标就会完成。
它们很容易设计:
# Simple tree definition
class Tree:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
# In-order lazy iterator (aka generator)
def inorder(tree):
if tree is not None:
for x in inorder(tree.left):
yield x
yield tree.data
for x in inorder(tree.right):
yield x
# Reverse in-order lazy iterator
def rev_inorder(tree):
if tree is not None:
for x in rev_inorder(tree.right):
yield x
yield tree.data
for x in rev_inorder(tree.left):
yield x
# Construct a tree
n1 = Tree(1)
n2 = Tree(2)
n3 = Tree(3) # 7
n4 = Tree(4) # / \
n5 = Tree(5, n1, n2) # 5 6
n6 = Tree(6, n3, n4) # / \ / \
n7 = Tree(7, n5, n6) # 1 2 3 4
for i in inorder(n7):
print i,
print
for i in rev_inorder(n7):
print i,
print
输出:
1 5 2 7 3 6 4
4 6 3 7 2 5 1
要手动迭代,请使用:
gen = rev_inorder(n7)
print gen.next() # Output 4
print gen.next() # Output 6
答案 1 :(得分:0)
我提出了一个简单的想法;-): 如果您不想为BST周围的迭代分配额外空间,则需要牺牲性能。
var inst = new BST();
inst.Insert(-121);
inst.Insert(13);
inst.Insert(1);
inst.Insert(10);
GetAddends(inst, 55); // here we go
function GetAddends(bst, target) {
var iter1 = bst.GetIterator();
var iter2 = bst.GetIterator(false);
while (iter1.IsValid() && iter2.IsValid() && (iter1.Pos() < iter2.Pos())) {
var temp = iter1.data() + iter2.data();
if (temp < target) iter1.Next();
else if (temp > target) iter2.Next();
else window.alert(iter1.data() + "+" + iter2.data() + "=" + target);
}
bst.ClearIterators();
}
function BST() {
var _root, _nodeCount, _locked;
this.Insert = function(data) {
if (_locked === true) throw "could not modify the BST during iteration";
_nodeCount++;
}
this.Delete = function(data) {
if (_locked === true) throw "could not modify the BST during iteration";
_nodeCount--;
return null;
}
this.GetIterator = function(isForward) { return Iter(isForward); }
this.ClearIterators = function() { _locked = false; }
function Iter(isForward) {
if (isForward == null) isForward = true; // if the parameter is omitted, then true by default
_locked = true;
var _pos = isForward ? 0 : (_nodeCount - 1);
var _curData;
return function() {
this.IsValid() {
return (isForward ? (_pos < _nodeCount) : (_pos >= 0));
}
this.Next = function() {
isForward ? _pos++ : _pos--;
_curData = null;
}
this.Pos = function() { return _pos; }
this.Data = function() {
if (_curData == null) { /* loop the BST and find _posTH node and stored in the _curData in case we need it later */ }
return _curData;
}
}
}
}
这些代码没有实现BST,但这个想法应该是明确的。玩得开心!提醒一下,我们不允许在持有迭代器的过程中修改BST。在我们不在持有迭代器的范围内之后,我们需要调用ClearIterators()。但是,一个优雅的解决方案可能是使用PUB / SUB让BST知道存在多少迭代器。也许这可能是另一个问题,哈哈。