I found this problem and I am not very sure if my approach approach is right:
"A binary tree can be encoded using
two functions l and r such that for a
node n, l(n) gives the left child of
n(or nil if there is none) and r(n)
gives the right child(or nil if there
is none).Let Test(l,r,x) be a simple
recursive algorithm for taking a
binary tree encoded by the l and r
functions together with the root node
x for the binary tree, and returns
"yes" if no node in the tree has
exactly one child. Give the pseudocode
for this algorithm."
I tried this:
test(l,r,x)
if((l(x)!=null && r(x)!=null) || (l(x)==null && r(x)==null))
return "yes"
else return "no"
if(test(l,r,l(x))=="yes") test (l,r,l(x)) else return "no"
if(test(l,r,r(x))=="yes") test (l,r,r(x)) else return "no"
return "yes"
Is it correct? If l and r are functions, why are they passed as normal parameters when the function is called?
Thank you in advance for your answers!
You have three basic conditions: both children are null, one child is null, or neither child is null. I'd test them in that order as well (because it simplifies the logic a bit):
if l(x) == null && r(x) == null
return true;
if l(x) == null || r(x) == null // only need inclusive OR, due to previous test.
return false;
return test(l, r, l(x)) && test(l, r, r(x))
As far as passing l and r as parameters goes, it all depends: some languages (e.g., functional languages) allow you to pass a function as a parameter. Others (e.g., C, C++, etc.) have you pass a pointer to a function instead -- but it's pretty much irrelevant. A few won't let you pass anything like a function, in which case you'd have to hardwire it in. In this case, you're not really gaining much (anything?) by passing l and r as parameters anyway. Passing a function as a parameter is useful primarily when/if the receiving function doesn't know what function it's going to receive a priori (which it does here).
the first thing you do is either return yes or no, so the last part is unreachable.
I would change it so that if you have one child, you return no, otherwise you return yes or no depending on if your children meet the criteria.
test(l,r,x)
if((l(x)!=null && r(x)==null) || (l(x)==null && r(x)!=null))
return "no"
if(l(x) == null && r(x) == null)
return "yes"
return test(l,r,l(x)) && test(l,r,r(x))
I don't think this is correct. The problem I see is in the first step:
if((l(x)!=null && r(x)!=null) || (l(x)==null && r(x)==null))
return "yes"
else return "no"
The problem is that you cannot determine the 'yes' for the entire tree at the first step. What you have to do is break it up into components:
if this node has both children
return the result of test(l,r,l(x)) && (test(l,r,r(x))
if this node has no children
return true
if this node has 1 child
return false
as per your last question ("If l and r are functions, why are they passed as normal parameters when the function is called?"), the answer is that they don't have to be passed as parameters. That's just the notation they chose when they said "A binary tree can be encoded using two functions l and r [...]"
Related
def dfs(s,d):
def dfs_helper(s,d):
if s==d:
return True
if s in visited:
return False
visited.add(s)
for c in graph[s]:
dfs_helper(c,d)
return False
visited = set()
return dfs_helper(s,d)
I'm not sure why the above code is correct. I saw this in a paper but shouldn't it say return dfs_helper(c,d) instead of just dfs_helper(c,d) when looping through all the neighbors? Otherwise, how do we return anything all the way up since I thought returns only take you one level up to the immediate caller.
I.e. if we have a graph with edges (A,B), (A,C), and (C,D), I get why the dfs_helper(D,D) returns True, but when we run dfs_helper(C,D), we just run dfs_helper(D,D) but we aren't RETURNING dfs_helper(D,D) so True does not get passed back up. Shouldn't that be the case? And if not, why is that so?
Fixed this. It turns out I was on the right track.
I needed to change from
for c in graph[s]:
dfs_helper(c,d)
to
for c in graph[s]:
if dfs_helper(c,d): return True
pseudocode:
// deprecated x!=y && hash(x) == hash(y) // how to make this true?
x!=y && hash(x) == hash(y) && (z!=x && z!=y) && (hash(x) != hash(z) && (hash(y) != hash(z)) // how to make this true?
x and y can be any readable value
Whatever the language, the pseudocode is just help to understand what I mean.
I just wonder how to implement such hash function.
PS: For math, i am an idiot. I can not imagine if there is an algorithm that can do this.
UPDATE 1:
The pseudocode has bug, so I updated the code(actually still has bug, never mind, I will explain).
My original requirement is to make a hash function that can return same value for different parameter, and the parameter value should contains some rule. It means, only the parameter value in same category would gets same hash code, others are not.
e.g.
The following expressions are clearly(you can treat '0' as placeholder):
hash("1.1") == hash("1.0") == hash("0.1")
hash("2.2") == hash("2.0") == hash("0.2")
and
hash("2.2") != hash("2.1") != hash("1.2")
I think this question can do such description:
There are two or more different values contains implied same attribute.
Only these values have such same attribute in the world.
The attribute can obtain through some way(maybe a function), hash() will call it inside.
hash() one of the values, you can retrive the attribute, then you can get the unique hashCode.
It's looks like hash collision, but we exactly know what they are. Also looks like many-to-one model.
How to design collision rules? The values could be any character or numeric. And how to implement the designs?
PPS: This is a question full of bugs, maybe the updated parts cannot explain the the problem either. Or maybe this is a false proposition. I want abstract my issue as a general model, but it makes my mind overflowed. If necessary I will post my actual issue that I am facing.
Any constant hash trivially satisfies your condition:
hash(v) = 42
A less constant answer than yuri kilocheck's would be to use the mod operator:
hash(v) = v % 10;
Then you'll have:
hash(1) = 1
hash(2) = 2
hash(3) = 3
...
hash(11) = 1
hash(12) = 2
This error appears sometimes only when I call a recursive function of which one of the parameters is a number: rand()%10. Just like in the code down below:
private: System::Void AIrandomMove(int randomMove,String ^s)
{
if (randomMove == 1)
{
if ( Move(1) ) // move number 1 had already been done
AIrandomMove(rand()%10,s); // here it appears the System.StackOverflowException
else
//do move number 1
}
//same goes for ==2 || ==3 || ... || ==10
}
How can I handle this?
A proper recursive algorithm works under two assumptions:
you have a base case which terminate the recursion (so the function doesn't call itself)
you have a recursive case which invokes the function itself with different arguments so that there is some progression involved
This translates in something like:
void recursive(inArgs) {
if (condition)
return;
else
recursive(outArgs)
}
It's clear that if condition is the expression true then this code never terminates (hence it will eventually raise a stack overflow).
In your situation condition is evaluated through a random value comparison. Now, assume condition is rand()%2 == 0. So basically each time it is evaluated you have 50% chance of being true and 50% of being false.
This doesn't guarantee that the recursion will terminate, as a path with n true evaluation exists (and it probability can be calculated). That's the problem with your design.
If many moves have been already made (or maybe all of them) then recursion won't end.
You don't need recursion at all in your case, since you could store the available moves in a set and remove them once they are not available anymore (possibly shuffling the set to then choose one randomly). Or even a simpler solution would be something like:
int choosenMove = rand()%10;
while (Move(choosenMove)) {
choosenMove = rand()%10;
// do move choosenMove
}
But this doesn't guarantee termination neither if you don't make sure that a state in which no moves are available can't happen.
I have homeowork to write pseudo code to check if a valid binary tree is a search binary tree.
I created an array to hold the in-order values of the tree. if the in-order values are in decreasing order it means it is indeed BST. However I've got some problem with the recursion in the method InOverArr.
I need to update the index of the array in order to submit the values to the array in the order they are at the tree.
I'm not sure the index is really updated properly during the recursion.. is it or not? and if you see some problem can you help me fix this? thanks a lot
pseudo code
first function
IsBST(node)
size ← TreeSize(node)
create new array TreeArr of Size number of cells
index ← 0
few comments:
now we use the IN_ORDER procedure with a small variation , I called the new version of the procedure: InOrderArr
the pseudo code of InOrderArr is described below IsBST
InOrderArr(node, TreeArr, index)
for i from 1 to size-1 do
if not (TreeArr[i] > TreeArr[i-1]) return
false
return true
second function
InOrderArr (node, Array, index)
if node = NULL then return
else
InOrderArr (node.left, Array, index)
treeArr[index] = node.key
index ← index + 1
InOrderArr (node.right, Array, index)
Return
Your code is generally correct. Just three notes.
The correctness of the code depends on the implementation, specifically on the way of index handling. Many programming languages pass arguments to subroutines by value. That means the subroutine receives a copy of the value and modifications made to the parameter have no effect on the original value. So incrementing index during execution of InOrderArr (node.left, Array, index) would not affect the position used by treeArr[index] = node.key. As a result only the rightmost path would be stored in the array.
To avoid that you'll have to ensure that index is passed by reference, so that incrementation done by a callee advances the position used later by a caller.
BST is usually defined so that the left subtreee of a node contains keys that are less than that node's key, and the right subtree contains nodes with greater keys – see Wikipedia's article on BST. Then the inorder traversal retrieves keys in ascending order. Why do you expect descending order?
Possibly it would be more efficient to drop the array and just recursively test a definition condition of BST?
Whenever we follow a left link we expect keys which are less than the current one. Whenever we follow the right link we expect keys greater the the current one. So for most subtrees there is some interval of keys values, defined by some ancestor nodes' keys. Just track those keys and test whether the key falls inside the current valid interval. Be sure to handle 'no left end defined' condition on the letfmost path and 'no right end' on the rightmost path of the tree. At the root node there's no ancestor yet, so the root key is not tested at all (any value is OK).
EDIT
C code draft:
// Test a node against its closest left-side and right-side ancestors
boolean isNodeBST(NODE *lt, NODE *node, NODE *rt)
{
if(node == NULL)
return true;
if(lt != NULL && node->key < lt->key)
return false;
if(rt != NULL && node->key > rt->key)
return false;
return
isNodeBST(lt, node->left, node) &&
isNodeBST(node, node->right, rt);
}
boolean isTreeBST(TREE *tree)
{
return isNodeBST( NULL, tree->root, NULL);
}
Recursion makes backtracking easy as it guarantees that you won't go through the same path again. So all ramifications of your path are visited just once. I am trying to convert a backtracking tail-recursive (with accumulators) algorithm to iteration. I heard it is supposed to be easy to convert a perfectly tail-recursive algorithm to iteration. But I am stuck in the backtracking part.
Can anyone provide a example through code so myself and others can visualize how backtracking is done? I would think that a STACK is not needed here because I have a perfectly tail-recursive algorithm using accumulators, but I can be wrong here.
If the function is actually recursive, then the transformation is as follows (and this is what a compiler which understand TCO will do for you, so you shouldn't have to do it yourself):
Original:
function func(a1, a2, a3...)
... doesn't contain either return or call
return val
...
return func(x1, x2, x3...)
...
... etc.
Converted to:
function func(a1, a2, a3...)
func: // label for goto (yuk!)
...
return val // No change
...
a1 = x1; a2 = x2; a3 = x3...; goto func;
...
... etc.
In order to make this transformation work with mutually co-recursive functions, you need to combine them into a single function, each of which comes with a label. As above, simple return statements are not altered, and return foo(...) turn into assignment to parameter variables followed by goto foo.
Of course, when combining the functions, you may need to rename local variables to avoid conflicts. And you will also lose the ability to use more than one top-level function, unless you add something like a switch statement (with gotos) at the top entry point, before any label. (In fact, in a language in which allowed goto case foo, you could just use the case labels as labels.)
The use of goto is, of course, ugly. If you use a language which preferably guarantees tail-call optimization, or failing that, at least makes a reasonable attempt to do it and reports when it fails, then there is absolutely no motivation to replace the recursive solution, which (in my opinion) is almost always more readable.
In some cases, it's possible to replace the goto and label with something like while (1) { ... }or other such loops, but that involves replacing thegotos withcontinue` (or equivalent), and that won't work if they're nested inside of other loops. So you can actually waste quite a lot of time making the ugly transformation slightly less ugly, and still not end up with a program as readable as the original.
I'll stop proselytizing recursion now. :)
Edited (I couldn't help it, sorry)
Here's a back-tracking n-queens solution in Lua (which does do TCO), consisting of a tail-recursive solver and a tail-recursive verifier:
function solve(legal, n, first, ...)
if first == nil -- Failure
then return nil
elseif first >= n -- Back-track
then return solve(legal, n, ...)
elseif not legal(first + 1, ...) -- Continue search
then return solve(legal, n, first + 1, ...)
elseif n == 1 + select("#", ...) -- Success
then return first + 1, ...
else -- Forward
return solve(legal, n, 0, first + 1, ...)
end
end
function queens_helper(dist, first, second, ...)
if second == nil
then return true
elseif first == second or first - dist == second or first + dist == second
then return false
else
return queens_helper(dist + 1, first, ...)
end
end
function queens_legal(...) return queens_helper(1, ...) end
-- in case you want to try n-rooks, although the solution is trivial.
function rooks_legal(first, second, ...)
if second == nil then return true
elseif first == second then return false
else return rooks_legal(first, ...)
end
end
function queens(n) return solve(queens_legal, n, 0) end