├── ALG_3rd.pdf ├── All Algorithms for competion └── ProgrammingCampSyllabus.pdf ├── C++STL ├── STL-Lectures.pdf └── lecture8.pdf ├── Cracking the Coding Interview, 4 Edition - 150 Programming Interview Questions and Solutions.pdf ├── Effective C++ ├── 0321334876.pdf └── Effective_C++_ Second Edition_190.pdf ├── Graph Algorithms II.pdf ├── Hacking_a_Google_Interview_Practice_Questions_Person_A.pdf ├── Programming Interviews Exposed.PDF ├── README.md ├── Wiley - Programming Interviews Exposed_Secrets to Landing Your Next Job (2000).pdf ├── afi-samples.pdf ├── are-you-smart-enough-to-work-at-google-9781851689170.pdf ├── binary trees ├── BinaryTrees.html └── BinaryTrees_files │ └── binarytree.gif ├── coding_interviews.pdf ├── crack_the _interview.pdf ├── cv_jobs_help.pdf ├── googles resume.pdf ├── interview-preparation-best-100-ashay-raut.pdf └── the-product-manager-handbook.pdf /ALG_3rd.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/ALG_3rd.pdf -------------------------------------------------------------------------------- /All Algorithms for competion/ProgrammingCampSyllabus.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/All Algorithms for competion/ProgrammingCampSyllabus.pdf -------------------------------------------------------------------------------- /C++STL/STL-Lectures.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/C++STL/STL-Lectures.pdf -------------------------------------------------------------------------------- /C++STL/lecture8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/C++STL/lecture8.pdf -------------------------------------------------------------------------------- /Cracking the Coding Interview, 4 Edition - 150 Programming Interview Questions and Solutions.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/Cracking the Coding Interview, 4 Edition - 150 Programming Interview Questions and Solutions.pdf -------------------------------------------------------------------------------- /Effective C++/0321334876.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/Effective C++/0321334876.pdf -------------------------------------------------------------------------------- /Effective C++/Effective_C++_ Second Edition_190.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/Effective C++/Effective_C++_ Second Edition_190.pdf -------------------------------------------------------------------------------- /Graph Algorithms II.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/Graph Algorithms II.pdf -------------------------------------------------------------------------------- /Hacking_a_Google_Interview_Practice_Questions_Person_A.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/Hacking_a_Google_Interview_Practice_Questions_Person_A.pdf -------------------------------------------------------------------------------- /Programming Interviews Exposed.PDF: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/Programming Interviews Exposed.PDF -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Interview-Prep-for-CS- 2 | ====================== 3 | 4 | Preparation guides for preparing for big companies like google , microsoft , amazon etc. 5 | -------------------------------------------------------------------------------- /Wiley - Programming Interviews Exposed_Secrets to Landing Your Next Job (2000).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/Wiley - Programming Interviews Exposed_Secrets to Landing Your Next Job (2000).pdf -------------------------------------------------------------------------------- /afi-samples.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/afi-samples.pdf -------------------------------------------------------------------------------- /are-you-smart-enough-to-work-at-google-9781851689170.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/are-you-smart-enough-to-work-at-google-9781851689170.pdf -------------------------------------------------------------------------------- /binary trees/BinaryTrees.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Binary Trees 11 | 12 | 13 |
14 |

15 | Binary Trees

16 | 17 |
by Nick Parlante
18 | 19 |

This article introduces the basic concepts of binary trees, and then 20 | works through a series of practice problems with solution code in C/C++ 21 | and Java. Binary trees have an elegant recursive pointer structure, so 22 | they are a good way to learn recursive pointer algorithms. 23 |

24 | Contents

25 | Section 1. Binary Tree Structure -- a quick introduction 26 | to binary trees and the code that operates on them 27 |
Section 2. Binary Tree Problems -- practice problems 28 | in increasing order of difficulty 29 |
Section 3. C Solutions -- solution code to the 30 | problems for C and C++ programmers 31 |
Section 4. Java versions -- how binary trees work 32 | in Java, with solution code 33 |

34 | Stanford CS Education Library -- #110

35 | This is article #110 in the Stanford CS Education Library. This and other 36 | free CS materials are available at the library (http://cslibrary.stanford.edu/). 37 | That people seeking education should have the opportunity to find it. This 38 | article may be used, reproduced, excerpted, or sold so long as this paragraph 39 | is clearly reproduced. Copyright 2000-2001, Nick Parlante, nick.parlante@cs.stanford.edu. 40 |

41 | Related CSLibrary Articles

42 | 43 | 57 | 58 |

59 | Section 1 -- Introduction To Binary Trees

60 | A binary tree is made of nodes, where each node contains a "left" pointer, 61 | a "right" pointer, and a data element. The "root" pointer points to the 62 | topmost node in the tree. The left and right pointers recursively point 63 | to smaller "subtrees" on either side. A null pointer represents a binary 64 | tree with no elements -- the empty tree. The formal recursive definition 65 | is: a binary tree is either empty (represented by a null pointer), 66 | or is made of a single node, where the left and right pointers (recursive 67 | definition ahead) each point to a binary tree. 68 |
  69 |

a drawing of a little binary tree 70 |
  71 |

A "binary search tree" (BST) or "ordered binary tree" is a type of binary 72 | tree where the nodes are arranged in order: for each node, all elements 73 | in its left subtree are less-or-equal to the node (<=), and all the 74 | elements in its right subtree are greater than the node (>). The tree shown 75 | above is a binary search tree -- the "root" node is a 5, and its left subtree 76 | nodes (1, 3, 4) are <= 5, and its right subtree nodes (6, 9) are > 5. 77 | Recursively, each of the subtrees must also obey the binary search tree 78 | constraint: in the (1, 3, 4) subtree, the 3 is the root, the 1 <= 3 79 | and 4 > 3. Watch out for the exact wording in the problems -- a "binary 80 | search tree" is different from a "binary tree". 81 |

The nodes at the bottom edge of the tree have empty subtrees and are 82 | called "leaf" nodes (1, 4, 6) while the others are "internal" nodes (3, 83 | 5, 9). 84 |

85 | Binary Search Tree Niche

86 | Basically, binary search trees are fast at insert and lookup. The next 87 | section presents the code for these two algorithms. On average, a binary 88 | search tree algorithm can locate a node in an N node tree in order lg(N) 89 | time (log base 2). Therefore, binary search trees are good for "dictionary" 90 | problems where the code inserts and looks up information indexed by some 91 | key. The lg(N) behavior is the average case -- it's possible for a particular 92 | tree to be much slower depending on its shape. 93 |

94 | Strategy

95 | Some of the problems in this article use plain binary trees, and some use 96 | binary search trees. In any case, the problems concentrate on the combination 97 | of pointers and recursion. (See the articles linked above for pointer articles 98 | that do not emphasize recursion.) 99 |

For each problem, there are two things to understand... 100 |

108 | When thinking about a binary tree problem, it's often a good idea to draw 109 | a few little trees to think about the various cases. 110 |

111 | Typical Binary Tree Code in C/C++

112 | As an introduction, we'll look at the code for the two most basic binary 113 | search tree operations -- lookup() and insert(). The code here works for 114 | C or C++. Java programers can read the discussion here, and then look at 115 | the Java versions in Section 4. 116 |

In C or C++, the binary tree is built with a node type like this... 117 |

struct node { 118 |
    int data; 119 |
    struct node* left; 120 |
    struct node* right; 121 |
} 122 |
  123 |

124 | Lookup()

125 | Given a binary search tree and a "target" value, search the tree to see 126 | if it contains the target. The basic pattern of the lookup() code occurs 127 | in many recursive tree algorithms: deal with the base case where the tree 128 | is empty, deal with the current node, and then use recursion to deal with 129 | the subtrees. If the tree is a binary search tree, there is often some 130 | sort of less-than test on the node to decide if the recursion should go 131 | left or right. 132 |

/* 133 |
 Given a binary tree, return true if a node 134 |
 with the target data is found in the tree. Recurs 135 |
 down the tree, chooses the left or right 136 |
 branch by comparing the target to each node. 137 |
*/ 138 |
static int lookup(struct node* node, int target) { 139 |
  // 1. Base case == empty tree 140 |
  // in that case, the target is not found so return false 141 |
  if (node == NULL) { 142 |
    return(false); 143 |
  } 144 |
  else { 145 |
    // 2. see if found here 146 |
    if (target == node->data) return(true); 147 |
    else { 148 |
      // 3. otherwise recur down the correct 149 | subtree 150 |
      if (target < node->data) return(lookup(node->left, 151 | target)); 152 |
      else return(lookup(node->right, 153 | target)); 154 |
    } 155 |
  } 156 |
} 157 |
  158 |

The lookup() algorithm could be written as a while-loop that iterates 159 | down the tree. Our version uses recursion to help prepare you for the problems 160 | below that require recursion. 161 |

162 | Pointer Changing Code

163 | There is a common problem with pointer intensive code: what if a function 164 | needs to change one of the pointer parameters passed to it? For example, 165 | the insert() function below may want to change the root pointer. In C and 166 | C++, one solution uses pointers-to-pointers (aka "reference parameters"). 167 | That's a fine technique, but here we will use the simpler technique that 168 | a function that wishes to change a pointer passed to it will return 169 | the new value of the pointer to the caller. The caller is responsible for 170 | using the new value. Suppose we have a change() function that may change 171 | the the root, then a call to change() will look like this... 172 |

// suppose the variable "root" points to the tree 173 |
root = change(root); 174 |

We take the value returned by change(), and use it as the new value 175 | for root. This construct is a little awkward, but it avoids using reference 176 | parameters which confuse some C and C++ programmers, and Java does not 177 | have reference parameters at all. This allows us to focus on the recursion 178 | instead of the pointer mechanics. (For lots of problems that use reference 179 | parameters, see CSLibrary #105, Linked List Problems, http://cslibrary.stanford.edu/105/). 180 |

181 | Insert()

182 | Insert() -- given a binary search tree and a number, insert a new node 183 | with the given number into the tree in the correct place. The insert() 184 | code is similar to lookup(), but with the complication that it modifies 185 | the tree structure. As described above, insert() returns the new tree pointer 186 | to use to its caller. Calling insert() with the number 5 on this tree... 187 |

    2 188 |
   / \ 189 |
  1   10 190 |

returns the tree... 191 |

    2 192 |
   / \ 193 |
  1   10 194 |
     / 195 |
    5 196 |

The solution shown here introduces a newNode() helper function that 197 | builds a single node. The base-case/recursion structure is similar to the 198 | structure in lookup() -- each call checks for the NULL case, looks at the 199 | node at hand, and then recurs down the left or right subtree if needed. 200 |

/* 201 |
 Helper function that allocates a new node 202 |
 with the given data and NULL left and right 203 |
 pointers. 204 |
*/ 205 |
struct node* NewNode(int data) { 206 |
  struct node* node = new(struct node);    207 | // "new" is like "malloc" 208 |
  node->data = data; 209 |
  node->left = NULL; 210 |
  node->right = NULL; 211 |

  return(node); 212 |
} 213 |
  214 |

/* 215 |
 Give a binary search tree and a number, inserts a new node 216 |
 with the given number in the correct place in the tree. 217 |
 Returns the new root pointer which the caller should 218 |
 then use (the standard trick to avoid using reference 219 |
 parameters). 220 |
*/ 221 |
struct node* insert(struct node* node, int data) { 222 |
  // 1. If the tree is empty, return a new, single node 223 |
  if (node == NULL) { 224 |
    return(newNode(data)); 225 |
  } 226 |
  else { 227 |
    // 2. Otherwise, recur down the tree 228 |
    if (data <= node->data) node->left = insert(node->left, 229 | data); 230 |
    else node->right = insert(node->right, data); 231 |

    return(node); // return the (unchanged) node 232 | pointer 233 |
  } 234 |
} 235 |
  236 |

The shape of a binary tree depends very much on the order that the nodes 237 | are inserted. In particular, if the nodes are inserted in increasing order 238 | (1, 2, 3, 4), the tree nodes just grow to the right leading to a linked 239 | list shape where all the left pointers are NULL. A similar thing happens 240 | if the nodes are inserted in decreasing order (4, 3, 2, 1). The linked 241 | list shape defeats the lg(N) performance. We will not address that issue 242 | here, instead focusing on pointers and recursion. 243 |

244 | Section 2 -- Binary Tree Problems

245 | Here are 14 binary tree problems in increasing order of difficulty. Some 246 | of the problems operate on binary search trees (aka "ordered binary trees") 247 | while others work on plain binary trees with no special ordering. The next 248 | section, Section 3, shows the solution code in C/C++. 249 | Section 250 | 4 gives the background and solution code in Java. The basic structure 251 | and recursion of the solution code is the same in both languages -- the 252 | differences are superficial. 253 |

Reading about a data structure is a fine introduction, but at some point 254 | the only way to learn is to actually try to solve some problems starting 255 | with a blank sheet of paper. To get the most out of these problems, you 256 | should at least attempt to solve them before looking at the solution. Even 257 | if your solution is not quite right, you will be building up the right 258 | skills. With any pointer-based code, it's a good idea to make memory drawings 259 | of a a few simple cases to see how the algorithm should work. 260 |

261 | 1. build123()

262 | This is a very basic problem with a little pointer manipulation. (You can 263 | skip this problem if you are already comfortable with pointers.) Write 264 | code that builds the following little 1-2-3 binary search tree... 265 |

    2 266 |
   / \ 267 |
  1   3 268 |

Write the code in three different ways... 269 |

280 | (In Java, write a build123() method that operates on the receiver to change 281 | it to be the 1-2-3 tree with the given coding constraints. See Section 282 | 4.) 283 |

struct node* build123() { 284 |
  285 |

286 | 2. size()

287 | This problem demonstrates simple binary tree traversal. Given a binary 288 | tree, count the number of nodes in the tree. 289 |

int size(struct node* node) { 290 |
  291 |

292 | 3. maxDepth()

293 | Given a binary tree, compute its "maxDepth" -- the number of nodes along 294 | the longest path from the root node down to the farthest leaf node. The 295 | maxDepth of the empty tree is 0, the maxDepth of the tree on the first 296 | page is 3. 297 |

int maxDepth(struct node* node) { 298 |
  299 |

300 | 4. minValue()

301 | Given a non-empty binary search tree (an ordered binary tree), return the 302 | minimum data value found in that tree. Note that it is not necessary to 303 | search the entire tree. A maxValue() function is structurally very similar 304 | to this function. This can be solved with recursion or with a simple while 305 | loop. 306 |

int minValue(struct node* node) { 307 |
  308 |

309 | 5. printTree()

310 | Given a binary search tree (aka an "ordered binary tree"), iterate over 311 | the nodes to print them out in increasing order. So the tree... 312 |

       4 313 |
      / \ 314 |
     2   5 315 |
    / \ 316 |
   1   3 317 |

Produces the output "1 2 3 4 5". This is known as an "inorder" traversal 318 | of the tree. 319 |

Hint: For each node, the strategy is: recur left, print the node 320 | data, recur right. 321 |

void printTree(struct node* node) { 322 |
  323 |

324 | 6. printPostorder()

325 | Given a binary tree, print out the nodes of the tree according to a bottom-up 326 | "postorder" traversal -- both subtrees of a node are printed out completely 327 | before the node itself is printed, and each left subtree is printed before 328 | the right subtree. So the tree... 329 |

       4 330 |
      / \ 331 |
     2   5 332 |
    / \ 333 |
   1   3 334 |

Produces the output "1 3 2 5 4". The description is complex, but the 335 | code is simple. This is the sort of  bottom-up traversal that would 336 | be used, for example, to evaluate an expression tree where a node is an 337 | operation like '+' and its subtrees are, recursively, the two subexpressions 338 | for the '+'. 339 |

void printPostorder(struct node* node) { 340 |
  341 |

342 | 7. hasPathSum()

343 | We'll define a "root-to-leaf path" to be a sequence of nodes in a tree 344 | starting with the root node and proceeding downward to a leaf (a node with 345 | no children). We'll say that an empty tree contains no root-to-leaf paths. 346 | So for example, the following tree has exactly four root-to-leaf paths: 347 |

              348 | 5 349 |
             350 | / \ 351 |
            352 | 4   8 353 |
           /   354 | / \ 355 |
          11  356 | 13  4 357 |
         /  \      358 | \ 359 |
        7    360 | 2      1 361 |

Root-to-leaf paths: 362 |
   path 1: 5 4 11 7 363 |
   path 2: 5 4 11 2 364 |
   path 3: 5 8 13 365 |
   path 4: 5 8 4 1 366 |

For this problem, we will be concerned with the sum of the values of 367 | such a path -- for example, the sum of the values on the 5-4-11-7 path 368 | is 5 + 4 + 11 + 7 = 27. 369 |

Given a binary tree and a sum, return true if the tree has a root-to-leaf 370 | path such that adding up all the values along the path equals the given 371 | sum. Return false if no such path can be found. (Thanks to Owen Astrachan 372 | for suggesting this problem.) 373 |

int hasPathSum(struct node* node, int sum) { 374 |
  375 |

376 | 8. printPaths()

377 | Given a binary tree, print out all of its root-to-leaf paths as defined 378 | above. This problem is a little harder than it looks, since the "path so 379 | far" needs to be communicated between the recursive calls. Hint: 380 | In C, C++, and Java, probably the best solution is to create a recursive 381 | helper function printPathsRecur(node, int path[], int pathLen), where the 382 | path array communicates the sequence of nodes that led up to the current 383 | call. Alternately, the problem may be solved bottom-up, with each node 384 | returning its list of paths. This strategy works quite nicely in Lisp, 385 | since it can exploit the built in list and mapping primitives. (Thanks 386 | to Matthias Felleisen for suggesting this problem.) 387 |

Given a binary tree, print out all of its root-to-leaf paths, one per 388 | line. 389 |

void printPaths(struct node* node) { 390 |
  391 |

392 | 9. mirror()

393 | Change a tree so that the roles of the left and right pointers are swapped 394 | at every node. 395 |

 So the tree... 396 |
       4 397 |
      / \ 398 |
     2   5 399 |
    / \ 400 |
   1   3 401 |

 is changed to... 402 |
       4 403 |
      / \ 404 |
     5   2 405 |
        / \ 406 |
       3   1 407 |

The solution is short, but very recursive. As it happens, this can be 408 | accomplished without changing the root node pointer, so the return-the-new-root 409 | construct is not necessary. Alternately, if you do not want to change the 410 | tree nodes, you may construct and return a new mirror tree based on the 411 | original tree. 412 |

void mirror(struct node* node) { 413 |
  414 |

415 | 10. doubleTree()

416 | For each node in a binary search tree, create a new duplicate node, and 417 | insert the duplicate as the left child of the original node. The resulting 418 | tree should still be a binary search tree. 419 |

 So the tree... 420 |
    2 421 |
   / \ 422 |
  1   3 423 |

 is changed to... 424 |
       2 425 |
      / \ 426 |
     2   3 427 |
    /   / 428 |
   1   3 429 |
  / 430 |
 1 431 |

As with the previous problem, this can be accomplished without changing 432 | the root node pointer. 433 |

void doubleTree(struct node* node) { 434 |
  435 |

436 | 11. sameTree()

437 | Given two binary trees, return true if they are structurally identical 438 | -- they are made of nodes with the same values arranged in the same way. 439 | (Thanks to Julie Zelenski for suggesting this problem.) 440 |

int sameTree(struct node* a, struct node* b) { 441 |
  442 |

443 | 12. countTrees()

444 | This is not a binary tree programming problem in the ordinary sense -- 445 | it's more of a math/combinatorics recursion problem that happens to use 446 | binary trees. (Thanks to Jerry Cain for suggesting this problem.) 447 |

Suppose you are building an N node binary search tree with the values 448 | 1..N. How many structurally different  binary search trees are there 449 | that store those values? Write a recursive function that, given the number 450 | of distinct values, computes the number of structurally unique binary search 451 | trees that store those values. For example, countTrees(4) should return 452 | 14, since there are 14  structurally unique binary search trees that 453 | store 1, 2, 3, and 4. The base case is easy, and the recursion is short 454 | but dense. Your code should not construct any actual trees; it's just a 455 | counting problem. 456 |

int countTrees(int numKeys) { 457 |
  458 |
  459 |

460 | Binary Search Tree Checking (for problems 13 and 14)

461 | This background is used by the next two problems: Given a plain binary 462 | tree, examine the tree to determine if it meets the requirement to be a 463 | binary search tree. To be a binary search tree, for every node, all of 464 | the nodes in its left tree must be <= the node, and all of the nodes 465 | in its right subtree must be > the node. Consider the following four examples... 466 |

a.  5   -> TRUE 467 |
   / \ 468 |
  2   7 469 |
  470 |

b.  5   -> FALSE, because the 6 is not ok to the 471 | left of the 5 472 |
   / \ 473 |
  6   7 474 |
  475 |

c.   5  -> TRUE 476 |
    / \ 477 |
   2   7 478 |
  / 479 |
 1 480 |

d.   5  -> FALSE, the 6 is ok with the 2, but the 481 | 6 is not ok with the 5 482 |
    / \ 483 |
   2   7 484 |
  / \ 485 |
 1   6 486 |

For the first two cases, the right answer can be seen just by comparing 487 | each node to the two nodes immediately below it. However, the fourth case 488 | shows how checking the BST quality may depend on nodes which are several 489 | layers apart -- the 5 and the 6 in that case. 490 |
  491 |

492 | 13 isBST() -- version 1

493 | Suppose you have helper functions minValue() and maxValue() that return 494 | the min or max int value from a non-empty tree (see problem 3 above). Write 495 | an isBST() function that returns true if a tree is a binary search tree 496 | and false otherwise. Use the helper functions, and don't forget to check 497 | every node in the tree. It's ok if your solution is not very efficient. 498 | (Thanks to Owen Astrachan for the idea of having this problem, and comparing 499 | it to problem 14) 500 |

Returns true if a binary tree is a binary search tree. 501 |

int isBST(struct node* node) { 502 |
  503 |

504 | 14. isBST() -- version 2

505 | Version 1 above runs slowly since it traverses over some parts of the tree 506 | many times. A better solution looks at each node only once. The trick is 507 | to write a utility helper function isBSTRecur(struct node* node, int min, 508 | int max) that traverses down the tree keeping track of the narrowing min 509 | and max allowed values as it goes, looking at each node only once. The 510 | initial values for min and max should be INT_MIN and INT_MAX -- they narrow 511 | from there. 512 |

/* 513 |
 Returns true if the given tree is a binary search tree 514 |
 (efficient version). 515 |
*/ 516 |
int isBST2(struct node* node) { 517 |
  return(isBSTRecur(node, INT_MIN, INT_MAX)); 518 |
} 519 |

/* 520 |
 Returns true if the given tree is a BST and its 521 |
 values are >= min and <= max. 522 |
*/ 523 |
int isBSTRecur(struct node* node, int min, int max) { 524 |
  525 |

526 | 15. Tree-List

527 | The Tree-List problem is one of the greatest recursive pointer problems 528 | ever devised, and it happens to use binary trees as well. CLibarary #109 529 | http://cslibrary.stanford.edu/109/  530 | works through the Tree-List problem in detail and includes solution code 531 | in C and Java. The problem requires an understanding of binary trees, linked 532 | lists, recursion, and pointers. It's a great problem, but it's complex. 533 |
  534 |
  535 |

536 | Section 3 -- C/C++ Solutions

537 | Make an attempt to solve each problem before looking at the solution -- 538 | it's the best way to learn. 539 |

540 | 1. Build123() Solution (C/C++)

541 | // call newNode() three times 542 |
struct node* build123a() { 543 |
  struct node* root = newNode(2); 544 |
  struct node* lChild = newNode(1); 545 |
  struct node* rChild = newNode(3); 546 |

  root->left = lChild; 547 |
  root->right= rChild; 548 |

  return(root); 549 |
} 550 |

// call newNode() three times, and use only one local variable 551 |
struct node* build123b() { 552 |
  struct node* root = newNode(2); 553 |
  root->left = newNode(1); 554 |
  root->right = newNode(3); 555 |

  return(root); 556 |
} 557 |
  558 |

/* 559 |
 Build 123 by calling insert() three times. 560 |
 Note that the '2' must be inserted first. 561 |
*/ 562 |
struct node* build123c() { 563 |
  struct node* root = NULL; 564 |
  root = insert(root, 2); 565 |
  root = insert(root, 1); 566 |
  root = insert(root, 3); 567 |
  return(root); 568 |
} 569 |
  570 |

571 | 2. size() Solution (C/C++)

572 | /* 573 |
 Compute the number of nodes in a tree. 574 |
*/ 575 |
int size(struct node* node) { 576 |
  if (node==NULL) { 577 |
    return(0); 578 |
  } else { 579 |
    return(size(node->left) + 1 + size(node->right)); 580 |
  } 581 |
} 582 |
  583 |

584 | 3. maxDepth() Solution (C/C++)

585 | /* 586 |
 Compute the "maxDepth" of a tree -- the number of nodes along 587 |
 the longest path from the root node down to the farthest 588 | leaf node. 589 |
*/ 590 |
int maxDepth(struct node* node) { 591 |
  if (node==NULL) { 592 |
    return(0); 593 |
  } 594 |
  else { 595 |
    // compute the depth of each subtree 596 |
    int lDepth = maxDepth(node->left); 597 |
    int rDepth = maxDepth(node->right); 598 |

    // use the larger one 599 |
    if (lDepth > rDepth) return(lDepth+1); 600 |
    else return(rDepth+1); 601 |
  } 602 |
} 603 |
  604 |

605 | 4. minValue() Solution (C/C++)

606 | /* 607 |
 Given a non-empty binary search tree, 608 |
 return the minimum data value found in that tree. 609 |
 Note that the entire tree does not need to be searched. 610 |
*/ 611 |
int minValue(struct node* node) { 612 |
  struct node* current = node; 613 |

  // loop down to find the leftmost leaf 614 |
  while (current->left != NULL) { 615 |
    current = current->left; 616 |
  } 617 |

  return(current->data); 618 |
} 619 |
  620 |

621 | 5. printTree() Solution (C/C++)

622 | /* 623 |
 Given a binary search tree, print out 624 |
 its data elements in increasing 625 |
 sorted order. 626 |
*/ 627 |
void printTree(struct node* node) { 628 |
  if (node == NULL) return; 629 |

  printTree(node->left); 630 |
  printf("%d ", node->data); 631 |
  printTree(node->right); 632 |
} 633 |
  634 |

635 | 6. printPostorder() Solution (C/C++)

636 | /* 637 |
 Given a binary tree, print its 638 |
 nodes according to the "bottom-up" 639 |
 postorder traversal. 640 |
*/ 641 |
void printPostorder(struct node* node) { 642 |
  if (node == NULL) return; 643 |

  // first recur on both subtrees 644 |
  printTree(node->left); 645 |
  printTree(node->right); 646 |

  // then deal with the node 647 |
  printf("%d ", node->data); 648 |
} 649 |
  650 |

651 | 7. hasPathSum() Solution (C/C++)

652 | /* 653 |
 Given a tree and a sum, return true if there is a path from 654 | the root 655 |
 down to a leaf, such that adding up all the values along 656 | the path 657 |
 equals the given sum. 658 |

 Strategy: subtract the node value from the sum when recurring 659 | down, 660 |
 and check to see if the sum is 0 when you run out of tree. 661 |
*/ 662 |
int hasPathSum(struct node* node, int sum) { 663 |
  // return true if we run out of tree and sum==0 664 |
  if (node == NULL) { 665 |
    return(sum == 0); 666 |
  } 667 |
  else { 668 |
  // otherwise check both subtrees 669 |
    int subSum = sum - node->data; 670 |
    return(hasPathSum(node->left, subSum) || 671 |
           hasPathSum(node->right, 672 | subSum)); 673 |
  } 674 |
} 675 |
  676 |

677 | 8. printPaths() Solution (C/C++)

678 | /* 679 |
 Given a binary tree, print out all of its root-to-leaf 680 |
 paths, one per line. Uses a recursive helper to do the work. 681 |
*/ 682 |
void printPaths(struct node* node) { 683 |
  int path[1000]; 684 |

  printPathsRecur(node, path, 0); 685 |
} 686 |

/* 687 |
 Recursive helper function -- given a node, and an array containing 688 |
 the path from the root node up to but not including this 689 | node, 690 |
 print out all the root-leaf paths. 691 |
*/ 692 |
void printPathsRecur(struct node* node, int path[], int pathLen) 693 | { 694 |
  if (node==NULL) return; 695 |

  // append this node to the path array 696 |
  path[pathLen] = node->data; 697 |
  pathLen++; 698 |

  // it's a leaf, so print the path that led to here 699 |
  if (node->left==NULL && node->right==NULL) { 700 |
    printArray(path, pathLen); 701 |
  } 702 |
  else { 703 |
  // otherwise try both subtrees 704 |
    printPathsRecur(node->left, path, pathLen); 705 |
    printPathsRecur(node->right, path, pathLen); 706 |
  } 707 |
} 708 |

// Utility that prints out an array on a line. 709 |
void printArray(int ints[], int len) { 710 |
  int i; 711 |
  for (i=0; i<len; i++) { 712 |
    printf("%d ", ints[i]); 713 |
  } 714 |
  printf("\n"); 715 |
} 716 |
  717 |

718 | 9. mirror() Solution (C/C++)

719 | /* 720 |
 Change a tree so that the roles of the 721 |
 left and right pointers are swapped at every node. 722 |

 So the tree... 723 |
       4 724 |
      / \ 725 |
     2   5 726 |
    / \ 727 |
   1   3 728 |

 is changed to... 729 |
       4 730 |
      / \ 731 |
     5   2 732 |
        / \ 733 |
       3   1 734 |
*/ 735 |
void mirror(struct node* node) { 736 |
  if (node==NULL) { 737 |
    return; 738 |
  } 739 |
  else { 740 |
    struct node* temp; 741 |

    // do the subtrees 742 |
    mirror(node->left); 743 |
    mirror(node->right); 744 |

    // swap the pointers in this node 745 |
    temp = node->left; 746 |
    node->left = node->right; 747 |
    node->right = temp; 748 |
  } 749 |
} 750 |
  751 |

752 | 10. doubleTree() Solution (C/C++)

753 | /* 754 |
 For each node in a binary search tree, 755 |
 create a new duplicate node, and insert 756 |
 the duplicate as the left child of the original node. 757 |
 The resulting tree should still be a binary search tree. 758 |

 So the tree... 759 |
    2 760 |
   / \ 761 |
  1   3 762 |

 Is changed to... 763 |
       2 764 |
      / \ 765 |
     2   3 766 |
    /   / 767 |
   1   3 768 |
  / 769 |
 1 770 |

*/ 771 |
void doubleTree(struct node* node) { 772 |
  struct node* oldLeft; 773 |

  if (node==NULL) return; 774 |

  // do the subtrees 775 |
  doubleTree(node->left); 776 |
  doubleTree(node->right); 777 |

  // duplicate this node to its left 778 |
  oldLeft = node->left; 779 |
  node->left = newNode(node->data); 780 |
  node->left->left = oldLeft; 781 |
} 782 |
  783 |

784 | 11. sameTree() Solution (C/C++)

785 | /* 786 |
 Given two trees, return true if they are 787 |
 structurally identical. 788 |
*/ 789 |
int sameTree(struct node* a, struct node* b) { 790 |
  // 1. both empty -> true 791 |
  if (a==NULL && b==NULL) return(true); 792 |

  // 2. both non-empty -> compare them 793 |
  else if (a!=NULL && b!=NULL) { 794 |
    return( 795 |
      a->data == b->data && 796 |
      sameTree(a->left, b->left) && 797 |
      sameTree(a->right, b->right) 798 |
    ); 799 |
  } 800 |
  // 3. one empty, one not -> false 801 |
  else return(false); 802 |
} 803 |
  804 |
  805 |

806 | 12. countTrees() Solution (C/C++)

807 | /* 808 |
 For the key values 1...numKeys, how many structurally unique 809 |
 binary search trees are possible that store those keys. 810 |

 Strategy: consider that each value could be the root. 811 |
 Recursively find the size of the left and right subtrees. 812 |
*/ 813 |
int countTrees(int numKeys) { 814 |

  if (numKeys <=1) { 815 |
    return(1); 816 |
  } 817 |
  else { 818 |
    // there will be one value at the root, with 819 | whatever remains 820 |
    // on the left and right each forming their 821 | own subtrees. 822 |
    // Iterate through all the values that could 823 | be the root... 824 |
    int sum = 0; 825 |
    int left, right, root; 826 |

    for (root=1; root<=numKeys; root++) { 827 |
      left = countTrees(root - 1); 828 |
      right = countTrees(numKeys - root); 829 |

      // number of possible trees with 830 | this root == left*right 831 |
      sum += left*right; 832 |
    } 833 |

    return(sum); 834 |
  } 835 |
} 836 |
  837 |
  838 |

839 | 13. isBST1() Solution (C/C++)

840 | /* 841 |
 Returns true if a binary tree is a binary search tree. 842 |
*/ 843 |
int isBST(struct node* node) { 844 |
  if (node==NULL) return(true); 845 |

  // false if the max of the left is > than us 846 |

  // (bug -- an earlier version had min/max backwards here) 847 |
  if (node->left!=NULL && maxValue(node->left) > node->data) 848 |
    return(false); 849 |

  // false if the min of the right is <= than us 850 |
  if (node->right!=NULL && minValue(node->right) <= 851 | node->data) 852 |
    return(false); 853 |

  // false if, recursively, the left or right is not a BST 854 |
  if (!isBST(node->left) || !isBST(node->right)) 855 |
    return(false); 856 |

  // passing all that, it's a BST 857 |
  return(true); 858 |
} 859 |
  860 |
  861 |

862 | 14. isBST2() Solution (C/C++)

863 | /* 864 |
 Returns true if the given tree is a binary search tree 865 |
 (efficient version). 866 |
*/ 867 |
int isBST2(struct node* node) { 868 |
  return(isBSTUtil(node, INT_MIN, INT_MAX)); 869 |
} 870 |

/* 871 |
 Returns true if the given tree is a BST and its 872 |
 values are >= min and <= max. 873 |
*/ 874 |
int isBSTUtil(struct node* node, int min, int max) { 875 |
  if (node==NULL) return(true); 876 |

  // false if this node violates the min/max constraint 877 |
  if (node->data<min || node->data>max) return(false); 878 |

  // otherwise check the subtrees recursively, 879 |
  // tightening the min or max constraint 880 |
  return 881 |
    isBSTUtil(node->left, min, node->data) && 882 |
    isBSTUtil(node->right, node->data+1, max) 883 |
  ); 884 |
} 885 |
  886 |

887 | 15. TreeList Solution (C/C++)

888 | The solution code in C and Java to the great Tree-List recursion problem 889 | is in CSLibrary #109  http://cslibrary.stanford.edu/109/ 890 |

891 | Section 4 -- Java Binary Trees and Solutions

892 | In Java, the key points in the recursion are exactly the same as in C or 893 | C++. In fact, I created the Java solutions by just copying the C solutions, 894 | and then making the syntactic changes. The recursion is the same, however 895 | the outer structure is slightly different. 896 |

In Java, we will have a BinaryTree object that contains a single root 897 | pointer. The root pointer points to an internal Node class that behaves 898 | just like the node struct in the C/C++ version. The Node class is private 899 | -- it is used only for internal storage inside the BinaryTree and is not 900 | exposed to clients. With this OOP structure, almost every operation has 901 | two methods: a one-line method on the BinaryTree that starts the computation, 902 | and a recursive method that works on the Node objects. For the lookup() 903 | operation, there is a BinaryTree.lookup() method that the client uses to 904 | start a lookup operation. Internal to the BinaryTree class, there is a 905 | private recursive lookup(Node) method that implements the recursion down 906 | the Node structure. This second, private recursive method is basically 907 | the same as the recursive C/C++ functions above -- it takes a Node argument 908 | and uses recursion to iterate over the pointer structure. 909 |

910 | Java Binary Tree Structure

911 | To get started, here are the basic definitions for the Java BinaryTree 912 | class, and the lookup() and insert() methods as examples... 913 |

// BinaryTree.java 914 |
public class BinaryTree { 915 |
  // Root node pointer. Will be null for an empty tree. 916 |
  private Node root; 917 |
  918 |

  /* 919 |
   --Node-- 920 |
   The binary tree is built using this nested node class. 921 |
   Each node stores one data element, and has left and 922 | right 923 |
   sub-tree pointer which may be null. 924 |
   The node is a "dumb" nested class -- we just use it 925 | for 926 |
   storage; it does not have any methods. 927 |
  */ 928 |
  private static class Node { 929 |
    Node left; 930 |
    Node right; 931 |
    int data; 932 |

    Node(int newData) { 933 |
      left = null; 934 |
      right = null; 935 |
      data = newData; 936 |
    } 937 |
  } 938 |

  /** 939 |
   Creates an empty binary tree -- a null root pointer. 940 |
  */ 941 |
  public void BinaryTree() { 942 |
    root = null; 943 |
  } 944 |
  945 |

  /** 946 |
   Returns true if the given target is in the binary 947 | tree. 948 |
   Uses a recursive helper. 949 |
  */ 950 |
  public boolean lookup(int data) { 951 |
    return(lookup(root, data)); 952 |
  } 953 |
  954 |

  /** 955 |
   Recursive lookup  -- given a node, recur 956 |
   down searching for the given data. 957 |
  */ 958 |
  private boolean lookup(Node node, int data) { 959 |
    if (node==null) { 960 |
      return(false); 961 |
    } 962 |

    if (data==node.data) { 963 |
      return(true); 964 |
    } 965 |
    else if (data<node.data) { 966 |
      return(lookup(node.left, data)); 967 |
    } 968 |
    else { 969 |
      return(lookup(node.right, data)); 970 |
    } 971 |
  } 972 |
  973 |

  /** 974 |
   Inserts the given data into the binary tree. 975 |
   Uses a recursive helper. 976 |
  */ 977 |
  public void insert(int data) { 978 |
    root = insert(root, data); 979 |
  } 980 |
  981 |

  /** 982 |
   Recursive insert -- given a node pointer, recur down 983 | and 984 |
   insert the given data into the tree. Returns the new 985 |
   node pointer (the standard way to communicate 986 |
   a changed pointer back to the caller). 987 |
  */ 988 |
  private Node insert(Node node, int data) { 989 |
    if (node==null) { 990 |
      node = new Node(data); 991 |
    } 992 |
    else { 993 |
      if (data <= node.data) { 994 |
        node.left = insert(node.left, 995 | data); 996 |
      } 997 |
      else { 998 |
        node.right = insert(node.right, 999 | data); 1000 |
      } 1001 |
    } 1002 |

    return(node); // in any case, return the new 1003 | pointer to the caller 1004 |
  } 1005 |
  1006 |

1007 | OOP Style vs. Recursive Style

1008 | From the client point of view, the BinaryTree class demonstrates good OOP 1009 | style -- it encapsulates the binary tree state, and the client sends messages 1010 | like lookup() and insert() to operate on that state. Internally, the Node 1011 | class and the recursive methods 1012 | do not demonstrate OOP style. The 1013 | recursive methods like insert(Node) and lookup (Node, int) basically look 1014 | like recursive functions in any language. In particular, they do not operate 1015 | against a "receiver" in any special way. Instead, the recursive methods 1016 | operate on the arguments that are passed in which is the classical way 1017 | to write recursion. My sense is that the OOP style and the recursive style 1018 | do not be combined nicely for binary trees, so I have left them separate. 1019 | Merging the two styles would be especially awkward for the "empty" tree 1020 | (null) case, since you can't send a message to the null pointer. It's possible 1021 | to get around that by having a special object to represent the null tree, 1022 | but that seems like a distraction to me. I prefer to keep the recursive 1023 | methods simple, and use different examples to teach OOP. 1024 |

1025 | Java Solutions

1026 | Here are the Java solutions to the 14 binary tree problems. Most of the 1027 | solutions use two methods:a one-line OOP method that starts the computation, 1028 | and a recursive method that does the real operation. Make an attempt to 1029 | solve each problem before looking at the solution -- it's the best way 1030 | to learn. 1031 |

1032 | 1. Build123() Solution (Java)

1033 | /** 1034 |
 Build 123 using three pointer variables. 1035 |
*/ 1036 |
public void build123a() { 1037 |
  root = new Node(2); 1038 |
  Node lChild = new Node(1); 1039 |
  Node rChild = new Node(3); 1040 |

  root.left = lChild; 1041 |
  root.right= rChild; 1042 |
} 1043 |

/** 1044 |
 Build 123 using only one pointer variable. 1045 |
*/ 1046 |
public void build123b() { 1047 |
  root = new Node(2); 1048 |
  root.left = new Node(1); 1049 |
  root.right = new Node(3); 1050 |
} 1051 |
  1052 |

/** 1053 |
 Build 123 by calling insert() three times. 1054 |
 Note that the '2' must be inserted first. 1055 |
*/ 1056 |
public void build123c() { 1057 |
  root = null; 1058 |
  root = insert(root, 2); 1059 |
  root = insert(root, 1); 1060 |
  root = insert(root, 3); 1061 |
} 1062 |
  1063 |

1064 | 2. size() Solution (Java)

1065 | /** 1066 |
 Returns the number of nodes in the tree. 1067 |
 Uses a recursive helper that recurs 1068 |
 down the tree and counts the nodes. 1069 |
*/ 1070 |
public int size() { 1071 |
  return(size(root)); 1072 |
} 1073 |

private int size(Node node) { 1074 |
  if (node == null) return(0); 1075 |
  else { 1076 |
    return(size(node.left) + 1 + size(node.right)); 1077 |
  } 1078 |
} 1079 |
  1080 |

1081 | 3. maxDepth() Solution (Java)

1082 | /** 1083 |
 Returns the max root-to-leaf depth of the tree. 1084 |
 Uses a recursive helper that recurs down to find 1085 |
 the max depth. 1086 |
*/ 1087 |
public int maxDepth() { 1088 |
  return(maxDepth(root)); 1089 |
} 1090 |

private int maxDepth(Node node) { 1091 |
  if (node==null) { 1092 |
    return(0); 1093 |
  } 1094 |
  else { 1095 |
    int lDepth = maxDepth(node.left); 1096 |
    int rDepth = maxDepth(node.right); 1097 |

    // use the larger + 1 1098 |
    return(Math.max(lDepth, rDepth) + 1); 1099 |
  } 1100 |
} 1101 |
  1102 |

1103 | 4. minValue() Solution (Java)

1104 | /** 1105 |
 Returns the min value in a non-empty binary search tree. 1106 |
 Uses a helper method that iterates to the left to find 1107 |
 the min value. 1108 |
*/ 1109 |
public int minValue() { 1110 |
 return( minValue(root) ); 1111 |
} 1112 |
  1113 |

/** 1114 |
 Finds the min value in a non-empty binary search tree. 1115 |
*/ 1116 |
private int minValue(Node node) { 1117 |
  Node current = node; 1118 |
  while (current.left != null) { 1119 |
    current = current.left; 1120 |
  } 1121 |

  return(current.data); 1122 |
} 1123 |

1124 | 5. printTree() Solution (Java)

1125 | /** 1126 |
 Prints the node values in the "inorder" order. 1127 |
 Uses a recursive helper to do the traversal. 1128 |
*/ 1129 |
public void printTree() { 1130 |
 printTree(root); 1131 |
 System.out.println(); 1132 |
} 1133 |

private void printTree(Node node) { 1134 |
 if (node == null) return; 1135 |

 // left, node itself, right 1136 |
 printTree(node.left); 1137 |
 System.out.print(node.data + "  "); 1138 |
 printTree(node.right); 1139 |
} 1140 |
  1141 |

1142 | 6. printPostorder() Solution (Java)

1143 | /** 1144 |
 Prints the node values in the "postorder" order. 1145 |
 Uses a recursive helper to do the traversal. 1146 |
*/ 1147 |
public void printPostorder() { 1148 |
 printPostorder(root); 1149 |
 System.out.println(); 1150 |
} 1151 |

public void printPostorder(Node node) { 1152 |
  if (node == null) return; 1153 |

  // first recur on both subtrees 1154 |
  printPostorder(node.left); 1155 |
  printPostorder(node.right); 1156 |

  // then deal with the node 1157 |
 System.out.print(node.data + "  "); 1158 |
} 1159 |
  1160 |

1161 | 7. hasPathSum() Solution (Java)

1162 | /** 1163 |
 Given a tree and a sum, returns true if there is a path from 1164 | the root 1165 |
 down to a leaf, such that adding up all the values along 1166 | the path 1167 |
 equals the given sum. 1168 |

 Strategy: subtract the node value from the sum when recurring 1169 | down, 1170 |
 and check to see if the sum is 0 when you run out of tree. 1171 |
*/ 1172 |
public boolean hasPathSum(int sum) { 1173 |
 return( hasPathSum(root, sum) ); 1174 |
} 1175 |

boolean hasPathSum(Node node, int sum) { 1176 |
  // return true if we run out of tree and sum==0 1177 |
  if (node == null) { 1178 |
    return(sum == 0); 1179 |
  } 1180 |
  else { 1181 |
  // otherwise check both subtrees 1182 |
    int subSum = sum - node.data; 1183 |
    return(hasPathSum(node.left, subSum) || hasPathSum(node.right, 1184 | subSum)); 1185 |
  } 1186 |
} 1187 |
  1188 |

1189 | 8. printPaths() Solution (Java)

1190 | /** 1191 |
 Given a binary tree, prints out all of its root-to-leaf 1192 |
 paths, one per line. Uses a recursive helper to do the work. 1193 |
*/ 1194 |
public void printPaths() { 1195 |
  int[] path = new int[1000]; 1196 |
  printPaths(root, path, 0); 1197 |
} 1198 |

/** 1199 |
 Recursive printPaths helper -- given a node, and an array 1200 | containing 1201 |
 the path from the root node up to but not including this 1202 | node, 1203 |
 prints out all the root-leaf paths. 1204 |
*/ 1205 |
private void printPaths(Node node, int[] path, int pathLen) { 1206 |
  if (node==null) return; 1207 |

  // append this node to the path array 1208 |
  path[pathLen] = node.data; 1209 |
  pathLen++; 1210 |

  // it's a leaf, so print the path that led to here 1211 |
  if (node.left==null && node.right==null) { 1212 |
    printArray(path, pathLen); 1213 |
  } 1214 |
  else { 1215 |
  // otherwise try both subtrees 1216 |
    printPaths(node.left, path, pathLen); 1217 |
    printPaths(node.right, path, pathLen); 1218 |
  } 1219 |
} 1220 |

/** 1221 |
 Utility that prints ints from an array on one line. 1222 |
*/ 1223 |
private void printArray(int[] ints, int len) { 1224 |
  int i; 1225 |
  for (i=0; i<len; i++) { 1226 |
   System.out.print(ints[i] + " "); 1227 |
  } 1228 |
  System.out.println(); 1229 |
} 1230 |
  1231 |

1232 | 9. mirror() Solution (Java)

1233 | 1234 |


/** 1235 |
 Changes the tree into its mirror image. 1236 |

 So the tree... 1237 |
       4 1238 |
      / \ 1239 |
     2   5 1240 |
    / \ 1241 |
   1   3 1242 |

 is changed to... 1243 |
       4 1244 |
      / \ 1245 |
     5   2 1246 |
        / \ 1247 |
       3   1 1248 |

 Uses a recursive helper that recurs over the tree, 1249 |
 swapping the left/right pointers. 1250 |
*/ 1251 |
public void mirror() { 1252 |
  mirror(root); 1253 |
} 1254 |

private void mirror(Node node) { 1255 |
  if (node != null) { 1256 |
    // do the sub-trees 1257 |
    mirror(node.left); 1258 |
    mirror(node.right); 1259 |

    // swap the left/right pointers 1260 |
    Node temp = node.left; 1261 |
    node.left = node.right; 1262 |
    node.right = temp; 1263 |
  } 1264 |
} 1265 |
  1266 |

1267 | 10. doubleTree() Solution (Java)

1268 | /** 1269 |
 Changes the tree by inserting a duplicate node 1270 |
 on each nodes's .left. 1271 |
  1272 |
  1273 |

 So the tree... 1274 |
    2 1275 |
   / \ 1276 |
  1   3 1277 |

 Is changed to... 1278 |
       2 1279 |
      / \ 1280 |
     2   3 1281 |
    /   / 1282 |
   1   3 1283 |
  / 1284 |
 1 1285 |

 Uses a recursive helper to recur over the tree 1286 |
 and insert the duplicates. 1287 |
*/ 1288 |
public void doubleTree() { 1289 |
 doubleTree(root); 1290 |
} 1291 |

private void doubleTree(Node node) { 1292 |
  Node oldLeft; 1293 |

  if (node == null) return; 1294 |

  // do the subtrees 1295 |
  doubleTree(node.left); 1296 |
  doubleTree(node.right); 1297 |

  // duplicate this node to its left 1298 |
  oldLeft = node.left; 1299 |
  node.left = new Node(node.data); 1300 |
  node.left.left = oldLeft; 1301 |
} 1302 |
  1303 |

1304 | 11. sameTree() Solution (Java)

1305 | /* 1306 |
 Compares the receiver to another tree to 1307 |
 see if they are structurally identical. 1308 |
*/ 1309 |
public boolean sameTree(BinaryTree other) { 1310 |
 return( sameTree(root, other.root) ); 1311 |
} 1312 |

/** 1313 |
 Recursive helper -- recurs down two trees in parallel, 1314 |
 checking to see if they are identical. 1315 |
*/ 1316 |
boolean sameTree(Node a, Node b) { 1317 |
  // 1. both empty -> true 1318 |
  if (a==null && b==null) return(true); 1319 |

  // 2. both non-empty -> compare them 1320 |
  else if (a!=null && b!=null) { 1321 |
    return( 1322 |
      a.data == b.data && 1323 |
      sameTree(a.left, b.left) && 1324 |
      sameTree(a.right, b.right) 1325 |
    ); 1326 |
  } 1327 |
  // 3. one empty, one not -> false 1328 |
  else return(false); 1329 |
} 1330 |
  1331 |

1332 | 12. countTrees() Solution (Java)

1333 | /** 1334 |
 For the key values 1...numKeys, how many structurally unique 1335 |
 binary search trees are possible that store those keys? 1336 |

 Strategy: consider that each value could be the root. 1337 |
 Recursively find the size of the left and right subtrees. 1338 |
*/ 1339 |
public static int countTrees(int numKeys) { 1340 |
  if (numKeys <=1) { 1341 |
    return(1); 1342 |
  } 1343 |
  else { 1344 |
    // there will be one value at the root, with 1345 | whatever remains 1346 |
    // on the left and right each forming their 1347 | own subtrees. 1348 |
    // Iterate through all the values that could 1349 | be the root... 1350 |
    int sum = 0; 1351 |
    int left, right, root; 1352 |

    for (root=1; root<=numKeys; root++) { 1353 |
      left = countTrees(root-1); 1354 |
      right = countTrees(numKeys - root); 1355 |

      // number of possible trees with 1356 | this root == left*right 1357 |
      sum += left*right; 1358 |
    } 1359 |

    return(sum); 1360 |
  } 1361 |
} 1362 |
  1363 |

1364 | 13. isBST1() Solution (Java)

1365 | /** 1366 |
 Tests if a tree meets the conditions to be a 1367 |
 binary search tree (BST). 1368 |
*/ 1369 |
public boolean isBST() { 1370 |
  return(isBST(root)); 1371 |
} 1372 |

/** 1373 |
 Recursive helper -- checks if a tree is a BST 1374 |
 using minValue() and maxValue() (not efficient). 1375 |
*/ 1376 |
private boolean isBST(Node node) { 1377 |
  if (node==null) return(true); 1378 |

  // do the subtrees contain values that do not 1379 |
  // agree with the node? 1380 |
  if (node.left!=null && maxValue(node.left) > node.data) 1381 | return(false); 1382 |
  if (node.right!=null && minValue(node.right) <= 1383 | node.data) return(false); 1384 |

  // check that the subtrees themselves are ok 1385 |
  return( isBST(node.left) && isBST(node.right) ); 1386 |
} 1387 |
  1388 |
  1389 |

1390 | 14. isBST2() Solution (Java)

1391 | /** 1392 |
 Tests if a tree meets the conditions to be a 1393 |
 binary search tree (BST). Uses the efficient 1394 |
 recursive helper. 1395 |
*/ 1396 |
public boolean isBST2() { 1397 |
 return( isBST2(root, Integer.MIN_VALUE, Integer.MAX_VALUE) 1398 | ); 1399 |
} 1400 |

/** 1401 |
  Efficient BST helper -- Given a node, and min and max values, 1402 |
  recurs down the tree to verify that it is a BST, and that 1403 | all 1404 |
  its nodes are within the min..max range. Works in O(n) time 1405 | -- 1406 |
  visits each node only once. 1407 |
*/ 1408 |
private boolean isBST2(Node node, int min, int max) { 1409 |
  if (node==null) { 1410 |
    return(true); 1411 |
  } 1412 |
  else { 1413 |
   // left should be in range  min...node.data 1414 |
    boolean leftOk = isBST2(node.left, min, node.data); 1415 |

    // if the left is not ok, bail out 1416 |
    if (!leftOk) return(false); 1417 |

    // right should be in range node.data+1..max 1418 |
    boolean rightOk = isBST2(node.right, node.data+1, 1419 | max); 1420 |

    return(rightOk); 1421 |
  } 1422 |
} 1423 |
  1424 |
  1425 |
  1426 | 1427 |

-------------------------------------------------------------------------------- /binary trees/BinaryTrees_files/binarytree.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/binary trees/BinaryTrees_files/binarytree.gif -------------------------------------------------------------------------------- /coding_interviews.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/coding_interviews.pdf -------------------------------------------------------------------------------- /crack_the _interview.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/crack_the _interview.pdf -------------------------------------------------------------------------------- /cv_jobs_help.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/cv_jobs_help.pdf -------------------------------------------------------------------------------- /googles resume.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/googles resume.pdf -------------------------------------------------------------------------------- /interview-preparation-best-100-ashay-raut.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/interview-preparation-best-100-ashay-raut.pdf -------------------------------------------------------------------------------- /the-product-manager-handbook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reach2arunprakash/Interview-Prep-for-CS-books-collection/04e85a28da478dd9f1ab33c6ac69ec62936b787a/the-product-manager-handbook.pdf --------------------------------------------------------------------------------