├── 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 |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 |
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 |
For each problem, there are two things to understand... 100 |
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 |
/*
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 |
// 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 |
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 |
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 |
2
266 |
/ \
267 |
1 3
268 |
Write the code in three different ways... 269 |
struct node* build123() {
284 |
285 |
int size(struct node* node) {
290 |
291 |
int maxDepth(struct node* node) {
298 |
299 |
int minValue(struct node* node) {
307 |
308 |
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 |
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 |
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 |
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 |
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 |
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 |
int sameTree(struct node* a, struct node* b) {
441 |
442 |
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 |
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 |
Returns true if a binary tree is a binary search tree. 501 |
int isBST(struct node* node) {
502 |
503 |
/*
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 |
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 |
// use the larger one
599 |
if (lDepth > rDepth) return(lDepth+1);
600 |
else return(rDepth+1);
601 |
}
602 |
}
603 |
604 |
// loop down to find the leftmost leaf
614 |
while (current->left != NULL) {
615 |
current = current->left;
616 |
}
617 |
return(current->data);
618 |
}
619 |
620 |
printTree(node->left);
630 |
printf("%d ", node->data);
631 |
printTree(node->right);
632 |
}
633 |
634 |
// 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 |
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 |
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 |
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 |
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 |
// 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 |
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 |
// 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 |
/*
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 |
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 |
// 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 |
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 |
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 |
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 |
/**
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 |
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 |
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 |
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 |
/**
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 |
/**
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 |
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 |
/**
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 |
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 |
/**
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 |
/**
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 |