27.10.2014 Views

Cracking the Coding Interview, 4 Edition - 150 Programming Interview Questions and Solutions

Cracking the Coding Interview, 4 Edition - 150 Programming Interview Questions and Solutions

Cracking the Coding Interview, 4 Edition - 150 Programming Interview Questions and Solutions

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Solutions</strong> to Chapter 4 | Trees <strong>and</strong> Graphs<br />

4.7 You have two very large binary trees: T1, with millions of nodes, <strong>and</strong> T2, with hundreds<br />

of nodes. Create an algorithm to decide if T2 is a subtree of T1.<br />

SOLUTION<br />

pg 54<br />

Note that <strong>the</strong> problem here specifies that T1 has millions of nodes—this means that we<br />

should be careful of how much space we use. Let’s say, for example, T1 has 10 million<br />

nodes—this means that <strong>the</strong> data alone is about 40 mb. We could create a string representing<br />

<strong>the</strong> inorder <strong>and</strong> preorder traversals. If T2’s preorder traversal is a substring of T1’s preorder<br />

traversal, <strong>and</strong> T2’s inorder traversal is a substring of T1’s inorder traversal, <strong>the</strong>n T2 is a substring<br />

of T1. We can check this using a suffix tree. However, we may hit memory limitations<br />

because suffix trees are extremely memory intensive. If this become an issue, we can use an<br />

alternative approach.<br />

Alternative Approach: The treeMatch procedure visits each node in <strong>the</strong> small tree at most<br />

once <strong>and</strong> is called no more than once per node of <strong>the</strong> large tree. Worst case runtime is at<br />

most O(n * m), where n <strong>and</strong> m are <strong>the</strong> sizes of trees T1 <strong>and</strong> T2, respectively. If k is <strong>the</strong> number<br />

of occurrences of T2’s root in T1, <strong>the</strong> worst case runtime can be characterized as O(n + k * m).<br />

1 boolean containsTree(TreeNode t1, TreeNode t2) {<br />

2 if (t2 == null) return true; // The empty tree is always a subtree<br />

3 else return subTree(t1, t2);<br />

4 }<br />

5<br />

6 boolean subTree(TreeNode r1, TreeNode r2) {<br />

7 if (r1 == null)<br />

8 return false; // big tree empty & subtree still not found.<br />

9 if (r1.data == r2.data) {<br />

10 if (matchTree(r1,r2)) return true;<br />

11 }<br />

12 return (subTree(r1.left, r2) || subTree(r1.right, r2));<br />

13 }<br />

14<br />

15 boolean matchTree(TreeNode r1, TreeNode r2) {<br />

16 if (r2 == null && r1 == null)<br />

17 return true; // nothing left in <strong>the</strong> subtree<br />

18 if (r1 == null || r2 == null)<br />

19 return false; // big tree empty & subtree still not found<br />

20 if (r1.data != r2.data)<br />

21 return false; // data doesn’t match<br />

22 return (matchTree(r1.left, r2.left) &&<br />

23 matchTree(r1.right, r2.right));<br />

24 }<br />

25 }<br />

CareerCup.com<br />

1 3 0

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!