├── 16-Moderate ├── 9-Operations.cpp ├── 7-Number-Max.cpp ├── 23-Rand7-from-Rand5.cpp ├── 1-Number-Swapper.md ├── 11-Diving-board.cpp ├── 17-Contigous-Sequence.cpp ├── 24-Pairs-with-sum.cpp ├── 22-Langton-Ant.cpp ├── 21-Sum-Swap.cpp ├── 20-T9.cpp ├── 5-ZeroesInFactorial.cpp ├── 13-Bisect-Squares.cpp ├── 3-Intersection-line-segment.cpp ├── 19-pond-size.cpp ├── 2-Word-Frequencies.cpp ├── 12-XML-Encoding.cpp ├── 10-No-Of-Living-People.cpp ├── 14-Best-Line.cpp ├── 25-LRU-Cache.cpp ├── 6-Smallest-Difference.cpp ├── 18-Pattern-Matching.cpp ├── 15-Master-Mind.cpp ├── 8-English-Int.cpp └── 16-Sub-Sort.cpp ├── 5-Bit-Manipulation ├── 5-Debugger.txt ├── truth-table.txt ├── 7-Pairwise-swap.cpp ├── Get-Set-Clear-Bit.cpp ├── 6-Conversion.cpp ├── BinaryToString.cpp ├── Insertion.cpp ├── 4-Next-Number.cpp ├── 8-Draw-Line.cpp └── 3-Flip-Bit-To-Win.cpp ├── 7-Object-Oriented-Design ├── ParkingLot │ ├── ParkingLot.cpp │ └── README.md ├── HashTable │ ├── Node.h │ ├── HashTableTest.cpp │ └── HashTable.h ├── CircularArray │ ├── CircularArrayTest.cpp │ └── CircularArray.h ├── CallCenter │ ├── Call.h │ ├── Employee.h │ └── CallHandler.cpp └── FileSystem │ └── README.md ├── 12-C-And-C++ ├── text.txt ├── DefaultValues.cpp ├── 2-Reverse-String.cpp ├── Virtual-Distructor.txt ├── CopyNodes.cpp ├── ClassAndInheritance.cpp ├── Shallow-Vs-Deep-Copy.txt ├── Aligned_malloc.cpp ├── 2D-Array-Mem-Alloc.cpp ├── VirtualFn.cpp ├── How-virtual-Function-work.txt ├── 1-Last-K-Lines.cpp ├── Volatile-In-C++.txt ├── SmartPointer.cpp └── HashTable-Vs-STL-Map.txt ├── 11-Testing ├── 1-Mistake.md ├── 4-Test-Webpage-without-any-tool.md ├── 2-Random-Crashes.md ├── 3-Chess-Test.md └── 6-Test-An-ATM.md ├── 17-Hard ├── 4-Missing-Number.cpp ├── 19-Missing-Two.md ├── 3-Random-Set.cpp ├── 1-Add-Without-Plus.cpp ├── 2-Shuffle.cpp ├── 9-Kth-Multiple.cpp ├── 20-Continous-median.cpp ├── 21-Volume-Of-Histogram.cpp ├── 14-Smallest-K-in-Array.cpp ├── 8-Circus-Tower.cpp ├── 16-The-Masseuse.cpp ├── 12-BiNode.cpp ├── 18-Shortest-Supersequence.cpp ├── 17-Multi-Search.cpp └── 5-Letters-And-Numbers.cpp ├── 6-Math-and-Logic-Puzzles ├── RopeBurning.txt ├── 1-The-Heavy-Pill.txt ├── NineBallProblem.txt ├── 4-Ants-On-A-Triangle.txt ├── 5-Jugs-Of-Water.txt ├── 2-Basketball.txt ├── 3-Dominos.txt ├── 10-Poison.txt ├── 7-The-Apocalypse.txt ├── 9-100_Lockers.txt ├── 8-Egg-Drop-Problem.txt ├── 6-Blue-Eyed-Island.txt └── ProbabilityTheory.md ├── 3-Stacks-And-Queues ├── ThreeStackWithOneArray.cpp ├── StackMin.cpp ├── SortStack.cpp ├── QueueUsingStack.cpp ├── StackOfPlates.cpp └── AnimalShelter.cpp ├── 1-Array-And-String ├── StringRotation.py ├── IsUnique.cpp ├── StringCompression.cpp ├── URLify.cpp ├── RotateMatirx.cpp ├── CheckPermutation.cpp ├── ZeroMatrix.cpp ├── PalindromePermutation.cpp └── OneAway.cpp ├── 8-Recursion-And-Dynamic-Programming ├── TripleSteps.cpp ├── RecursiveMultiply.cpp ├── AllValidParenthesis.cpp ├── PaintFill.cpp ├── MagicIndex.cpp ├── TowerOfHanio.cpp ├── PermutationWithDups.cpp ├── StackOfBoxes.cpp ├── PermutationWithoutDup.cpp ├── Coins.cpp ├── RobotInAGrid.cpp └── EightQueen.cpp ├── 4-Trees-and-Graphs ├── MinimalTree.cpp ├── Route-Between-Nodes.cpp ├── ListOfDepths.cpp ├── Successor.cpp ├── CheckSubTree.cpp ├── ValidateBST.cpp └── PathWithSum.cpp ├── LICENSE ├── 15-Threads-And-Lock └── README.md ├── 2-Linked-Lists ├── PalindromeLinkList.cpp ├── KthToLast.cpp ├── DeleteMiddleNode.cpp ├── RemoveDups.cpp ├── PartitionAroundNode.cpp ├── IntersectionOfLL.cpp ├── LoopDetectionInLL.cpp └── SumList.cpp └── 9-System-Design-And-Scalability ├── How-To-Approach.md ├── 4-Duplicate-URLs.md └── 2-Social-Networks ├── shortestPathInGraph.cpp └── bfs.cpp /16-Moderate/9-Operations.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Operations: 3 | Write methods to implement the multiply, subtract, and divide operations for integers. 4 | The results of all of these are integers. Use only the add operator. 5 | */ 6 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/5-Debugger.txt: -------------------------------------------------------------------------------- 1 | Explain what the following code does: (( n & ( n-1 )) == 0). 2 | 3 | n and n-1 must have no 1 in common. The value of n is a power of 2. 4 | The expression checks weather n is a power of 2. 5 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/ParkingLot/ParkingLot.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | To compile: g++ ParkingLot.cpp -o ParkingLot --std=c++14 3 | */ 4 | 5 | #include "ParkingLot.h" 6 | #include 7 | 8 | int main() { 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /12-C-And-C++/text.txt: -------------------------------------------------------------------------------- 1 | This file ise used by Read Last K lines cpp file. This is the first line. 2 | line 2 3 | line 3 4 | line 4 5 | line 5 6 | line 6 7 | line 7 8 | line 8 9 | line 9 10 | line 10 11 | line 11 12 | line 12 13 | second last line 14 | last line 15 | -------------------------------------------------------------------------------- /12-C-And-C++/DefaultValues.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int func( int a, int b=3 ) { 6 | return a + b; 7 | } 8 | 9 | int main() { 10 | cout<< "Default values " << endl; 11 | cout<< func( 10 ) << endl; 12 | cout<< func( 10, 20 ) << endl; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /11-Testing/1-Mistake.md: -------------------------------------------------------------------------------- 1 | Find the mistake in the following code: 2 | 3 | ```c++ 4 | unsigned int i; 5 | for (i = 100; i >= 0; --i ) 6 | printf("%d\n", i); 7 | ``` 8 | 9 | An unsigned int is, by definition, always greater than or equal to zero. The for loop condition 10 | will therefore always be true, and it will loop infinitely. 11 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/truth-table.txt: -------------------------------------------------------------------------------- 1 | NOT operation 2 | A ~A 3 | 0 1 4 | 1 0 5 | 6 | AND Operation 7 | 8 | A B A&B 9 | 0 0 0 10 | 0 1 0 11 | 1 0 0 12 | 1 1 1 13 | 14 | 15 | OR Operation 16 | 17 | A B A+B 18 | 0 0 0 19 | 0 1 1 20 | 1 0 1 21 | 1 1 1 22 | 23 | XOR Operation 24 | 25 | A B A^B 26 | 0 0 0 27 | 0 1 1 28 | 1 0 1 29 | 1 1 0 30 | -------------------------------------------------------------------------------- /16-Moderate/7-Number-Max.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Number Max: 3 | Write a method that finds the maximum of two numbers. You should not use if-else 4 | or any other comparison operator. 5 | 6 | Sol: a and b are two numbers. Get the most significant bit of a - b. 7 | 8 | k = a - b 9 | p = most significant bit of k. 10 | q = reverse of k 11 | return p*a + q*b; 12 | 13 | */ 14 | 15 | -------------------------------------------------------------------------------- /17-Hard/4-Missing-Number.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Missing Number: 3 | An array A contains all the integers from 0 to n, except for one number which 4 | is missing. In this problem, we cannot access an entire integer in A with a single operation. The 5 | elements of A are represented in binary, and the only operation we can use to access them is "fetch 6 | the jth bit of A[i]," which takes constant time. Write code to find the missing integer. Can you do it 7 | in O(n) time? 8 | */ 9 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/HashTable/Node.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template class Node { 4 | public: 5 | // for head node 6 | Node() { 7 | next = NULL; 8 | prev = NULL; 9 | } 10 | 11 | // for internal nodes in linked-list 12 | Node( K key, V value ) { 13 | key = key; 14 | value = value; 15 | next = NULL; 16 | prev = NULL; 17 | } 18 | 19 | K key; 20 | V value; 21 | Node *next; 22 | Node *prev; 23 | }; 24 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/HashTable/HashTableTest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Hash Table: 3 | Design and implement a hash table which uses chaining (linked lists) to handle collisions. 4 | 5 | To compile: 'g++ HashTableTest.cpp -o HashTableTest' 6 | */ 7 | 8 | #include "HashTable.h" 9 | 10 | using std::cout; 11 | using std::endl; 12 | 13 | int main() { 14 | HashTable< string, string > *ht = new HashTable(); 15 | cout<< ht->get_hash( "cat" ) << endl; 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/RopeBurning.txt: -------------------------------------------------------------------------------- 1 | You have two ropes, and each takes exactly one hour to burn. How would you use them to time exactly 15 2 | minutes? Note that the ropes are of uneven densities, so half the rope length-wise does not necessarily take 3 | half an hour to burn. 4 | 5 | Sol: Burn rope1 at both ends and rope2 at one end. When rope1 is completely burnt 30 mins would have 6 | passed. Now burn rope2 at other end also. The time elapsed since rope2 started burning from other end 7 | is 15 min. 8 | -------------------------------------------------------------------------------- /3-Stacks-And-Queues/ThreeStackWithOneArray.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Describe how you could use a single array to implement three stacks. 3 | */ 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | int Arr[ 100 ]; 10 | 11 | // Fixed allocation 12 | // Use [ 0, N/3 ) for stack1 13 | // Use [ N/3, 2N/3 ) for stack2 14 | // Use [ 2N/3 N ] for stack3 15 | // 16 | // keep fn to check for full before doing push 17 | // and empty before doing pop. 18 | // In full and empty check for limits definded for stack. 19 | 20 | int main() { 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/CircularArray/CircularArrayTest.cpp: -------------------------------------------------------------------------------- 1 | #include "CircularArray.h" 2 | #include 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() { 8 | int capacity = 100; 9 | CircularArray* ca = new CircularArray( capacity ); 10 | for( int i = 0; i < 80; i++ ) { 11 | ca->push_back( i*2 ); 12 | } 13 | cout<< "size " << ca->getSize() << endl; 14 | 15 | for( int i=0; i < 40; i++ ) { 16 | ca->push_back( i*2 ); 17 | } 18 | cout<< "size " << ca->getSize() << endl; 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/7-Pairwise-swap.cpp: -------------------------------------------------------------------------------- 1 | /* Pairwise Swap: 2 | Write a program to swap odd and even bits in an integer with as few instructions as 3 | possible (e.g., bit 0 and bit 1 are swapped, bit 2 and bit 3 are swapped, and so on). 4 | */ 5 | 6 | #include 7 | using std::cout; 8 | using std::endl; 9 | 10 | int pairwsiseSwap( int n ) { 11 | int evenMask = 0x55555555; // 0101 0101 ... 12 | int oddMask = 0xaaaaaaaa; // 1010 1010 ... 13 | 14 | return ( evenMask & n >>> 1 ) | ( oddMask & n << 1 ); 15 | } 16 | 17 | int main() { 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/1-The-Heavy-Pill.txt: -------------------------------------------------------------------------------- 1 | The Heavy Pill: 2 | You have 20 bottles of pills. 19 bottles have 1.0 gram pills, but one has pills of weight 3 | 1.1 grams. Given a scale that provides an exact measurement, how would you find the heavy 4 | bottle? You can only use the scale once. 5 | 6 | Solution: 7 | Take 1 pill from bottle 1 8 | 2 pill from bottle 2 9 | 3 pill from bollte 3 10 | ... 11 | 19 pill from bottle 19 12 | 20 pill from bottle 20 13 | 14 | sum upto n = n*(n+1)/2. 15 | 16 | The total weight should be 210 + 0.1*( bottle-no ). 17 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/ParkingLot/README.md: -------------------------------------------------------------------------------- 1 | ## Parking Lot 2 | > Design a parking lot using object-oriented principles. 3 | 4 | ### Assumptions 5 | 6 | - The parking lot has multiple levels. Each level has multiple rows of spots. 7 | - The parking lot can park motorcycles, cars, and buses. 8 | - The parking lot has motorcycle spots, compact spots, and large spots. 9 | - A motorcycle can park in any spot. 10 | - A car can park in either a single compact spot or a single large spot. 11 | - A bus can park in five large spots that are consecutive and within the same row. It cannot park in small 12 | spots. -------------------------------------------------------------------------------- /1-Array-And-String/StringRotation.py: -------------------------------------------------------------------------------- 1 | ''' 2 | String Rotation: 3 | Assume you have a method isSubstring which checks if one word is a substring of another. 4 | Given two strings, S1 and S2, write code to check if S2 is a rotation of S1 using only one 5 | call to isSubstring (e.g., "waterbottle" is a rotation of "erbottlewat"). 6 | ''' 7 | 8 | def isSubString( s1, s2 ): 9 | return s1 in s2 10 | 11 | origStr = "waterbottle" 12 | rotStr = "erbottlewat" 13 | 14 | def checkStringRotation( original, rotation ): 15 | return isSubString( original, rotation + rotation ) 16 | 17 | print checkStringRotation( origStr, rotStr ) 18 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/NineBallProblem.txt: -------------------------------------------------------------------------------- 1 | The "nine balls" question is a classic interview question. You have nine balls. Eight are of the same weight, 2 | and one is heavier. You are given a balance which tells you only whether the left side or the right side is 3 | heavier. Find the heavy ball in just two uses of the scale. 4 | 5 | Sol: If we divide the balls into sets of three items each, we will know after just one weighing which set has the 6 | heavy one. For the final set of three balls, we simply repeat this: put one ball off to the side and weigh two. 7 | Pick the heavier of the two. Or, if the balls are the same weight, pick the third one. 8 | -------------------------------------------------------------------------------- /16-Moderate/23-Rand7-from-Rand5.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Rand7 from Rand5: 3 | Implement a method rand7() given rand5(). That is, given a method that generates a 4 | random number between 0 and 4 (inclusive), write a method that generates a random 5 | number between 0 and 6 (inclusive). 6 | 7 | 7 can be represented in a sequence of 3 bits 8 | 9 | Use rand(5) to randomly fill each bit with 0 or 1. 10 | For e.g: call rand(5) and 11 | 12 | if the result is 1 or 2, fill the bit with 0 13 | if the result is 4 or 5, fill the bit with 1 14 | if the result is 3 , then ignore and do it again (rejection) 15 | 16 | This way we can fill 3 bits randomly with 0/1 and thus get a number from 1-7. 17 | */ 18 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/TripleSteps.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Triple Steps: 3 | A child is running up a staircase with n steps and can hop either 1 step, 2 steps, or 3 steps at a time. 4 | Implement a method to count how many possible ways the child can run up the stairs. 5 | */ 6 | 7 | #include 8 | 9 | using std::cout; 10 | using std::endl; 11 | 12 | int getways( int n ) { 13 | int arr[n + 1]; 14 | arr[0] = 1; 15 | arr[1] = 1; 16 | arr[2] = 2; 17 | for( int i = 3; i <= n; i++ ) { 18 | arr[i] = arr[i - 3] + arr[i - 2] + arr[i - 1]; 19 | } 20 | return arr[n]; 21 | } 22 | 23 | int main() { 24 | int n = 10; 25 | cout<< getways( n ) << endl; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /12-C-And-C++/2-Reverse-String.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a function void reverse( char* str) in C or C++ which 3 | reverses a null terminated string. 4 | */ 5 | 6 | #include 7 | 8 | using namespace std; 9 | 10 | void reverseString( string &input ) { 11 | int start = 0; 12 | int end = input.length(); 13 | 14 | char tmp; 15 | while( start <= end ) { 16 | tmp = input[ start] ; 17 | input[ start ] = input[ end ]; 18 | input[ end ] = tmp; 19 | 20 | start++; 21 | end--; 22 | } 23 | } 24 | 25 | int main() { 26 | string text = "This is a string. Reverse it.\0"; 27 | cout<< text << endl; 28 | reverseString( text ); 29 | cout<< text << endl; 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /16-Moderate/1-Number-Swapper.md: -------------------------------------------------------------------------------- 1 | ## Number Swapper: 2 | Write a function to swap a number in place (that is, without temporary variables). 3 | 4 | 5 | ## Solution: 6 | Lets picture a and b on a number line for case where a > b 7 | 8 | ```bash 9 | 10 | |---------|----------------| 11 | 0 b diff a 12 | ``` 13 | 14 | First, we briefly set a to diff, which is the right side of the above number line. 15 | Then, when we add b and diff ( and store that value in b ), we get a. 16 | We now have b = a and a = diff. All that's left to do is to set a equal to b - diff. 17 | 18 | ```c++ 19 | a = a - b; // a = diff 20 | b = b + a; // b now equals original a 21 | a = b - a; // a now equals original b 22 | ``` 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/RecursiveMultiply.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Recursive Multiply: 3 | Write a recursive function to multiply two positive integers without using the * operator. 4 | You can use addition, subtraction, and bit shifting, but you should minimize the number of 5 | those operations. 6 | */ 7 | 8 | #include 9 | 10 | using std::cout; 11 | using std::endl; 12 | 13 | // Assumes b is smaller than a 14 | int multiply( int a, int b ) { 15 | int result = 0; 16 | while( b ) { 17 | if( b & 1 ) { 18 | result += a; 19 | } 20 | b = b >> 1; 21 | a = a << 1; 22 | } 23 | return result; 24 | } 25 | 26 | int main() { 27 | cout<< multiply( 15, 12 ) << endl; 28 | cout<< multiply( 35, 31 ) << endl; 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/Get-Set-Clear-Bit.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using std::cout; 3 | 4 | bool getBit( int num, int i ) { 5 | return ( num & ( 1 << i ) ) != 0 ; 6 | } 7 | 8 | int setBit( int num, int i ) { 9 | return num | ( 1 << i ); 10 | } 11 | 12 | int clearBit( int num, int i ) { 13 | int mask = ~( 1 << i ); 14 | return num & mask; 15 | } 16 | 17 | // clear all bits from i through 0 (inclusive) 18 | int clearBitsIthrough0(int num, int i) { 19 | int mask = ( -1 << ( i + 1 ) ); 20 | return num & mask; 21 | } 22 | 23 | // set the ith bit to a value v 24 | int updateBits( int num, int i, bool bitIs1 ) { 25 | int value = bitIs1 ? 1 : 0; 26 | int mask = ~( 1 << i ); 27 | return ( num & mask ) | ( value << i ); 28 | } 29 | 30 | int main() { 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/4-Ants-On-A-Triangle.txt: -------------------------------------------------------------------------------- 1 | Ants on a Triangle: 2 | There are three ants on different vertices of a triangle. What is the probability of 3 | collision (between any two or all of them) if they start walking on the sides of the 4 | triangle? Assume that each ant randomly picks a direction, with either direction being 5 | equally likely to be chosen, and that they walk at the same speed. 6 | 7 | Similarly, find the probability of collision with n ants on an n-vertex polygon. 8 | 9 | Solution: 10 | The ants will not collide only if all of them are moving in same direction i.e. 11 | clockwise or anti-clockwise. 12 | All possible directions: {000, 001, 010, 011, 100, 101, 110, 111} 13 | 14 | P( same direction for 3 ants ) = 2/(2^3) 15 | 16 | For ants on a n-vertex polygon: = 2/(2^n) = 1/2^(n-1) 17 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/CallCenter/Call.h: -------------------------------------------------------------------------------- 1 | #include // std::string 2 | #include // std::cout, std::endl 3 | 4 | using std::string; 5 | using std::cout; 6 | using std::endl; 7 | 8 | enum Level { 9 | RESPONDENT = 1, 10 | MANAGER, 11 | DIRECTOR, 12 | }; 13 | 14 | // Forward declaration of Employee Class 15 | class Employee; 16 | 17 | class Call { 18 | string phoneNo; 19 | Level level; 20 | 21 | /* Note: Employee has to be pointer as we don't know about Employee 22 | class layout at this point */ 23 | Employee *handler; 24 | 25 | public: 26 | Call( string phoneNo ) { 27 | phoneNo = phoneNo; 28 | level = Level::RESPONDENT; 29 | } 30 | Level getLevel() { 31 | return level; 32 | } 33 | void setLevel( Level _level ) { 34 | level = _level; 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /17-Hard/19-Missing-Two.md: -------------------------------------------------------------------------------- 1 | ## Missing Two: 2 | You are given an array with all the numbers from 1 to N appearing exactly once, except 3 | for one number that is missing. How can you find the missing number in O(N) time and 4 | O(1) space? What if there were two numbers missing? 5 | 6 | ## Solution 1: 7 | When 1 number is missing. 8 | Get the sum n*(n-1)/2 and subtract each element in array from this. you would get the 9 | missing number. 10 | 11 | When 2 numbers are missing. 12 | Get the sum which will give x + y = n. 13 | Get the product which will give x*y = n where n is known. Use quadratic to find x and y. 14 | 15 | ## Solution 2: 16 | To find 1 missing number 17 | - 1. XOR all the array elements, let the result of XOR be X1. 18 | - 2. XOR all numbers from 1 to n, let XOR be X2. 19 | - 3. XOR of X1 and X2 gives the missing number. 20 | -------------------------------------------------------------------------------- /17-Hard/3-Random-Set.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Random Set: 3 | Write a method to randomly generate a set of m integers from an array of size n. Each 4 | element must have equal probability of being chosen. 5 | */ 6 | 7 | #include 8 | #include 9 | #include // rand 10 | #include 11 | 12 | using std::vector; 13 | using std::set; 14 | 15 | 16 | set getMRandomFromN( vector< int > v, int m ) { 17 | int randIndex; 18 | int tmp; 19 | int size = v.size(); 20 | for( int i=0; i < m; ++i ) { 21 | randIndex = i + rand() % ( size - i ); 22 | // move tmp to ith location 23 | tmp = v[ randIndex ]; 24 | v[ randIndex ] = v[ i ]; 25 | v[ i ] = tmp; 26 | } 27 | 28 | set< int > s; 29 | for( int i = 0; i < m; ++i ) { 30 | s.insert( v[i] ); 31 | } 32 | return s; 33 | } 34 | 35 | int main() { 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/HashTable/HashTable.h: -------------------------------------------------------------------------------- 1 | #include "Node.h" 2 | #include 3 | #include // std::hash 4 | 5 | using std::string; 6 | using std::hash; 7 | 8 | hash strHash; 9 | 10 | template< typename K, typename V > class HashTable { 11 | public: 12 | HashTable() {} 13 | 14 | void insert( K k, V v ) { 15 | int index = get_hash( k ) % capacity; 16 | // TODO: 17 | // search for k,v in array[ index ] 18 | // if key k is found then update the value 19 | // otherwise add k, v at the front 20 | } 21 | 22 | void erase( K k, V v ) { 23 | int index =get_hash( k ) % capacity; 24 | // TODO 25 | // if k, v is found then delete it 26 | } 27 | 28 | int get_hash( K key ) { 29 | return strHash( key ); 30 | } 31 | 32 | private: 33 | static const int capacity = 10; 34 | Node< string, string > array[ capacity ]; 35 | }; 36 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/6-Conversion.cpp: -------------------------------------------------------------------------------- 1 | /* Conversion: 2 | Write a function to determine the number of bits you would need to flip to convert 3 | integer A to integer B. 4 | 5 | EXAMPLE 6 | Input: 29 ( or: 11101 ) , 15 ( or: 1111 ) 7 | Output: 2 8 | */ 9 | 10 | #include 11 | using std::cout; 12 | using std::endl; 13 | 14 | // Each 1 in the XOR represents a bit that is different between A and B. 15 | // Therefore, to check the number of bits that are different between A 16 | // and B, we simply need to count the number of bits in A^B that are 1. 17 | 18 | // Alternate approach: 19 | // The operation c = c & (c - 1) will clear the least significant bit in c. 20 | int bitCountInAxorB( int a, int b ) { 21 | int count = 0; 22 | 23 | for( int i = a^b; i != 0; i = i * ( i-1 ) ) 24 | count++; 25 | 26 | return count; 27 | } 28 | 29 | int main() { 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/AllValidParenthesis.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Parens: 3 | Implement an algorithm to print all valid ( e.g., properly opened and closed ) combinations 4 | of n pairs of parentheses. 5 | EXAMPLE 6 | Input: 3 7 | Output: ( ( ( ) ) ), ( ( ) ( ) ), ( ( ) ) ( ), ( ) ( ( ) ), ( ) ( ) ( ) 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | using std::string; 14 | using std::cout; 15 | using std::endl; 16 | 17 | void balancedParen( int open, int close, int n, string paren ) { 18 | if( close == n ) { // complete balanced parenthesis 19 | cout<< paren << endl; 20 | return; 21 | } 22 | if( open < n ) { 23 | balancedParen( open + 1, close, n, paren + "(" ); 24 | } 25 | if( open > close ) { 26 | balancedParen( open, close + 1, n, paren + ")" ); 27 | } 28 | } 29 | 30 | int main() { 31 | int n = 3; 32 | balancedParen( 0, 0, n, "" ); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /16-Moderate/11-Diving-board.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Diving Board: You are building a diving board by placing a bunch of planks of wood end-to-end. 3 | There are two types of planks, one of length shorter and one of length longer. You must use 4 | exactly K planks of wood. Write a method to generate all possible lengths for the diving board. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::set; 13 | 14 | set allPossibleDivingBoardLen( int longerLen, int shorterLen, int k ) { 15 | int len = 0; 16 | set< int > allLengths; 17 | for( int i = 0; i < k; ++i ) { 18 | len = i*shorterLen + ( k - i )* longerLen; 19 | allLengths.insert( len ); 20 | } 21 | return allLengths; 22 | } 23 | 24 | int main() { 25 | int lenOfLongerPlank = 8; 26 | int lenOfShorterPlank = 3; 27 | int k = 25; 28 | allPossibleDivingBoardLen( lenOfLongerPlank, lenOfShorterPlank, k ); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /1-Array-And-String/IsUnique.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | /* 7 | Implement an algorithm to determine if a string has all unique characters. 8 | 9 | Notes: 10 | ASCII is a 7-bit code, representing 128 different characters. 11 | 12 | Ques to Ask: 13 | Is string ASCII or Unicode ? 14 | 15 | We assume ASCII for this example. 16 | */ 17 | 18 | bool isDupUsingHashTable( string input ) { 19 | if( input.length() > 128 ) { 20 | return true; 21 | } 22 | 23 | bool map[ 128 ] = { false }; 24 | for( int i=0; i < input.length(); i++ ) { 25 | if( map[ input[ i ] ] == true ) 26 | return true; 27 | else 28 | map[ input[ i ] ]= true; 29 | } 30 | return false; 31 | } 32 | 33 | int main() { 34 | string s = "Not Duplicate"; 35 | string s1 = "Not Duplicae"; 36 | cout<< isDupUsingHashTable( s ) << endl; 37 | cout<< isDupUsingHashTable( s1 ) << endl; 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/5-Jugs-Of-Water.txt: -------------------------------------------------------------------------------- 1 | Jugs of Water: 2 | You have a five-quart jug, a three-quart jug, and an unlimited supply of water ( but no 3 | measuring cups ). How would you come up with exactly four quarts of water? Note that the 4 | jugs are oddly shaped, such that filling up exactly "half" of the jug would be impossible. 5 | 6 | Solution: 7 | This question, like many puzzle questions, has a math/computer science root. If the two jug 8 | sizes are relatively prime, you can measure any value between 'one and the sum of the jug sizes'. 9 | 10 | 5 Quart | 3 Quart | Action 11 | ------------------------ 12 | 5 0 Filled 5-quart jug. 13 | 2 3 Filled 3-quart with S-quart's contents. 14 | 2 0 Dumped 3-quart. 15 | 0 2 Fill 3-quart with S-quart's contents. 16 | 5 2 Filled 5-quart. 17 | 4 3 Fill remainder of 3-quart with 5-quart. 18 | 4 Done! We have 4 quarts. 19 | -------------------------------------------------------------------------------- /12-C-And-C++/Virtual-Distructor.txt: -------------------------------------------------------------------------------- 1 | Why does a destructor in base class need to be declared virtual ? 2 | 3 | Let's think about why we have virtual methods to start with. Suppose we have the following code: 4 | 5 | class Foo { 6 | public: 7 | void f(); 8 | }; 9 | 10 | class Bar : public Foo { 11 | public: 12 | void f(); 13 | } 14 | 15 | Foo *p = new Bar(); 16 | p->f(); 17 | 18 | Calling p->f() will result in a call to Foo::f(). This is because p is a pointer to Foo, and f() is not virtual. 19 | To ensure that p->f() will invoke the most derived implementation of f(), we need to declare f() to be a virtual 20 | function. 21 | 22 | Now, let's go back to our destructor. Destructors are used to clean up memory and resources. If Foo's 23 | destructor were not virtual, then Foo's destructor would be called, even when p is really of type Bar. 24 | This is why we declare destructors to be virtual; we want to ensure that the destructor for the most derived 25 | class is called. 26 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/2-Basketball.txt: -------------------------------------------------------------------------------- 1 | Basketball: 2 | You have a basketball hoop and someone says that you can play one of two games. 3 | Game 1: You get one shot to make the hoop. 4 | Game 2: You get three shots and you have to make two of three shots. 5 | 6 | If p is the probability of making a particular shot, for which values of p should you pick one game 7 | or the other? 8 | 9 | Solution: 10 | 11 | Probability of winning Game 1: 12 | P( Game1 ) = p, by definition. 13 | 14 | Probability of winning Game 2: 15 | 16 | The probability of winning Game 2 is the probability of making exactly two shots out of three OR 17 | making all three shots. 18 | In other words: 19 | P( Game 2 ) = P(making all shots) + P(making 1 and 2 and missing 3) 20 | + P(making 1 and 3 and missing 2) + P(missing 1 and making 2 and 3) 21 | 22 | = p^3 + p*p*(p-1) + p*(p-1)*p + (p-1)*p*p 23 | = p^3 + 3( 1- p )*p^2 24 | = 3p^2 - 2p^3 25 | 26 | you should play Game 1 if P( Game1 ) > P( Game2 ). 27 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/BinaryToString.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Given a real number between 0 and 1 (e.g., 0.72) that is passed in as a double, print 3 | the binary representation. If the number cannot be represented accurately in binary with at most 32 4 | characters, print "ERROR:' 5 | */ 6 | 7 | #include 8 | using std::cout; 9 | using std::endl; 10 | 11 | #include 12 | using std::string; 13 | 14 | string binaryToString( double num ) { 15 | if( num > 1 || num < 0 ) { 16 | return "ERROR"; 17 | } 18 | 19 | int len = 0; 20 | string binaryRep = ""; 21 | while( num > 0 && len < 32 ) { 22 | num = num * 2; 23 | if( num >= 1 ) { 24 | binaryRep = binaryRep + "1"; 25 | num = num - 1; 26 | } else { 27 | binaryRep= binaryRep + "0"; 28 | } 29 | 30 | len++; 31 | } 32 | return binaryRep; 33 | } 34 | 35 | int main() { 36 | cout<< binaryToString( 0.72 ) << endl; 37 | cout<< binaryToString( 0.70 ) << endl; 38 | cout<< binaryToString( 0.95 ) << endl; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/Insertion.cpp: -------------------------------------------------------------------------------- 1 | /* Insertion: 2 | You are given two 32-bit numbers, N and M, and two bit positions, i and j. 3 | Write a method to insert M into N such that M starts at bit j and ends at 4 | bit i. You can assume that the bits j through i have enough space to fit 5 | all of M. That is, if M = 10011, you can assume that there are at least 5 6 | bits between j and i. You would not, for example, have j = 3 and i = 2, 7 | because M could not fully fit between bit 3 and bit 2. 8 | 9 | EXAMPLE 10 | Input: N = 10000000000, M = 10011, i = 2, j = 6 11 | Output: N = 10001001100 12 | */ 13 | 14 | #include 15 | using std::cout; 16 | using std::endl; 17 | 18 | int insert( int n, int m, int j, int i ) { 19 | // -1 is 11111111... 20 | // (1< 18 | 19 | using std::cout; 20 | using std::endl; 21 | 22 | int add( int a, int b ) { 23 | int res; 24 | int carry; 25 | 26 | res = a ^ b; 27 | carry = (a & b ) << 1; 28 | if( carry > 0 ) { 29 | return add( res, carry ); 30 | } 31 | return res; 32 | } 33 | 34 | int main() { 35 | int a = 112; 36 | int b = 47; 37 | cout<< add( a, b ) << endl; 38 | } 39 | -------------------------------------------------------------------------------- /16-Moderate/17-Contigous-Sequence.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Contiguous Sequence: 3 | You are given an array of integers (both positive and negative). Find the contiguous 4 | sequence with the largest sum. Return the sum. 5 | 6 | EXAMPLE 7 | 8 | Input 2, -8, 3, -2, 4, -10 9 | 10 | Output: 5 ( i.e. { 3, -2, 4 } ) 11 | */ 12 | 13 | // g++ 17-Contigous-Sequence.cpp --std=c++14 14 | 15 | #include 16 | #include 17 | 18 | using std::cout; 19 | using std::endl; 20 | using std::vector; 21 | 22 | int largestContigousSeq( vector seq ) { 23 | vector subSeqAtPos( seq.size() ); 24 | subSeqAtPos[0]= seq[0]; 25 | for( int i=1; i < seq.size(); ++i ) { 26 | subSeqAtPos[i] = seq[i] >= ( subSeqAtPos[i-1] + seq[i] )? seq[i] : subSeqAtPos[ i -1 ] + seq[i]; 27 | } 28 | 29 | int max=subSeqAtPos[0]; 30 | for( int i=1; i < seq.size(); ++i ) { 31 | max = max > subSeqAtPos[i] ? max : subSeqAtPos[i]; 32 | } 33 | return max; 34 | } 35 | 36 | int main() { 37 | vector< int > seq = { 2, -8, 3, -2, 4, -10 }; 38 | cout<< largestContigousSeq( seq ) << endl; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/PaintFill.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Paint Fill: 3 | Implement the "paint fill" function that one might see on many image editing programs. 4 | That is, given a screen (represented by a two-dimensional array of colors), a point, 5 | and a new color, fill in the surrounding area until the color changes from the original 6 | color. 7 | */ 8 | 9 | #include 10 | 11 | enum Color { Red, 12 | Green, 13 | Blue }; 14 | 15 | void paintFill( int row, int col, Color **arr, int numRow, int numCol, 16 | Color toFill, Color origCol ) { 17 | if( ( row < 0 || col < 0 ) || ( row >= numRow || col >= numCol ) ) { 18 | return; 19 | } else if( arr[ row ][ col ] == origCol ) { 20 | arr[ row ][ col ] = toFill; 21 | paintFill( row + 1, col, arr, numRow, numCol, toFill, origCol ); 22 | paintFill( row, col + 1, arr, numRow, numCol, toFill, origCol ); 23 | paintFill( row - 1, col, arr, numRow, numCol, toFill, origCol ); 24 | paintFill( row, col - 1, arr, numRow, numCol, toFill, origCol ); 25 | } 26 | } 27 | 28 | int main() { 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /12-C-And-C++/CopyNodes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Write a method that takes a pointer to a Node structure as a parameter 3 | and returns a complete copy of the passed in data structure. The Node 4 | data structure contains two pointers to other Nodes. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | struct Node { 13 | int key; 14 | Node *left; 15 | Node *right; 16 | }; 17 | 18 | map nodeMap; 19 | 20 | Node * copyNodes( Node *node ) { 21 | if( node == NULL ) 22 | return NULL; 23 | 24 | map::iterator it = nodeMap.find( node ); 25 | if( it != nodeMap.end() ) { 26 | // already visited node 27 | return it->second; 28 | } 29 | 30 | Node *copyNode = ( Node * ) malloc( sizeof( Node ) ); 31 | nodeMap[ node ] = copyNode; 32 | copyNode->key = node->key; 33 | 34 | copyNode->left = copyNodes( node->left ); 35 | copyNode->right = copyNodes( node->right ); 36 | return copyNode; 37 | } 38 | 39 | int main() { 40 | Node *root1; 41 | // create a graph ... 42 | Node *root2 = copyNodes( root1 ); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/CircularArray/CircularArray.h: -------------------------------------------------------------------------------- 1 | /* 2 | Circular Array: 3 | Implement a CircularArray class that supports an array-like data structure which 4 | can be efficiently rotated. If possible, the class should use a generic type 5 | ( also called a template ), and should support iteration via the standard 6 | for( Obj o : circularArray ) notation. 7 | */ 8 | 9 | // For iterator solution look at: https://github.com/sonugiri1043/Designing_CPP_Iterators 10 | 11 | template< typename T > class CircularArray { 12 | int capacity; // capacity of Circular array 13 | int size; // size of Circular array 14 | int head; // marks the.. 15 | T *array; 16 | 17 | public: 18 | CircularArray( int capacity ) : capacity( capacity ) 19 | { 20 | size = 0; 21 | head = -1; 22 | array = new T[ capacity ]; 23 | } 24 | 25 | void push_back( T item ) { 26 | head = ( head + 1 ) % capacity; 27 | array[ head % capacity ] = item; 28 | size = ( size + 1 ); 29 | size = size > capacity ? capacity : size; 30 | } 31 | 32 | int getSize() { 33 | return size; 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /4-Trees-and-Graphs/MinimalTree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Given a sorted (increasing order) array with unique integer elements, 3 | write an algorithm to create a binary search tree with minimal height. 4 | */ 5 | 6 | #include 7 | 8 | using namespace std; 9 | 10 | class Node { 11 | public: 12 | int key; 13 | Node *left; 14 | Node *right; 15 | }; 16 | 17 | Node * minimalTree( int arr[], int left, int right ) { 18 | /* 19 | The middle of each subsection of the array becomes the root 20 | of the node. The left half of the array will become our left 21 | subtree, and the right half of the array will become the right subtree. 22 | */ 23 | 24 | Node *node = NULL; 25 | if( left <= right ) { 26 | int mid = ( left + right )/2; // Assume no overflow 27 | node = new Node(); 28 | node->key = arr[ mid ]; 29 | node->left = minimalTree( arr, left, mid - 1); 30 | node->right = minimalTree( arr, mid + 1, right ); 31 | } 32 | return node; 33 | } 34 | 35 | int main() { 36 | int arr[ 10 ] = { 1, 2, 3, 5, 6, 8, 9, 12, 24, 30 }; 37 | Node* root = minimalTree( arr, 0, 9 ); 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Sonu Giri 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /4-Trees-and-Graphs/Route-Between-Nodes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Given a directed graph, design an algorithm to find out whether there is a 3 | route between two nodes. 4 | */ 5 | 6 | #include // top store ajcanent nodes of a node 7 | #include // for bfs walk 8 | #include // to mark visited node, to avoid cycle 9 | 10 | // Node structure 11 | class Node { 12 | public: 13 | int key; 14 | vector children; 15 | }; 16 | 17 | bool doesPathExist( Node *start, Node *end ) { 18 | if( start == end ) 19 | return true; 20 | 21 | map< Node*, bool > nodeMap; 22 | queue nodeQ; 23 | nodeQ.push( start ); 24 | 25 | Node *tmpNode; 26 | while( !nodeQ.empty() ) { 27 | tmpNode = nodeQ.top(); 28 | nodeQ.pop(); 29 | 30 | vector::iterator it; 31 | for( it = tmpNode->children.begin(): it != tmpNode->children.end(); it++ ) { 32 | if( nodeMap.find( *it ) == nodeMap.end() ) { 33 | // node is not visited before 34 | if( *it == end ) { 35 | return true; 36 | } else { 37 | nodeQ.push( *it ); 38 | } 39 | } 40 | } 41 | nodeMap[ tmpNode ] = true; 42 | } 43 | return false; 44 | } 45 | -------------------------------------------------------------------------------- /4-Trees-and-Graphs/ListOfDepths.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Given a binary tree, design an algorithm which creates a linked list 3 | of all the nodes at each depth ( e.g., if you have a tree with depth D, 4 | you 'll have D linked lists ). 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | class Node { 14 | public: 15 | int key; 16 | Node *left; 17 | Node *right; 18 | }; 19 | 20 | /* 21 | output is a vector of lists. 22 | each list contain nodes in tree at level i. 23 | */ 24 | vector< list > listsOfDepth( Node *node ) { 25 | vector< list< Node* > > arrayOfLinkList; 26 | 27 | list< Node * > curr; 28 | if( node != NULL ) { 29 | curr.push_back( node ); 30 | } 31 | 32 | while( curr.size() > 0 ) { 33 | arrayOfLinkList.push_back( curr ); // add nodes at curr level to vector 34 | 35 | list< Node * > parents = curr; 36 | list< Node * >::iterator it; 37 | curr.clear(); 38 | for( it = parents.begin(); it != parents.end(); it++ ) { 39 | curr.push_back( *it ); 40 | } 41 | } 42 | return arrayOfLinkList; 43 | } 44 | 45 | int main() { 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /11-Testing/4-Test-Webpage-without-any-tool.md: -------------------------------------------------------------------------------- 1 | ## No Test Tools: 2 | How would you load test a webpage without using any test tools? 3 | 4 | ## Solution 5 | Load testing helps to identify a web application's maximum operating capacity, as well as any bottlenecks 6 | that may interfere with its performance. Similarly, it can check how an application responds to variations 7 | in load. 8 | 9 | To perform load testing, we must first identify the performance critical scenarios and the metrics which 10 | fulfill our performance objectives. Typical criteria include: 11 | - Response time 12 | - Throughput 13 | - Resource utilization 14 | - Maximum load that the system can bear. 15 | 16 | In the absence of formal testing tools, we can basically create our own. For example, we could simulate 17 | concurrent users by creating thousands of virtual users. We would write a multi-threaded program with 18 | thousands of threads, where each thread acts as a real-world user loading the page. For each user, we would 19 | programmatically measure response time, data I/O, etc. 20 | 21 | We would then analyze the results based on the data gathered during the tests and compare it with the 22 | accepted values. -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/MagicIndex.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Magic Index: 3 | A magic index in an array A[ 0 ... n - 1 ] is defined to be an index such that A[ i ] = i. 4 | Given a sorted array of distinct integers, write a method to find a magic index, if one exists, 5 | in array A. 6 | FOLLOW UP 7 | What if the values are not distinct? 8 | */ 9 | 10 | #include 11 | 12 | using std::cout; 13 | using std::endl; 14 | 15 | int magicIndex( int arr[], int left, int right ) { 16 | if( left > right ) { 17 | return -1; 18 | } 19 | 20 | int mid = ( left + right )/2; 21 | if( arr[ mid ] == mid ) { 22 | return mid; 23 | } 24 | if( arr[ mid ] > mid ) { 25 | // search in left half 26 | return magicIndex( arr, left, mid - 1 ); 27 | } else { 28 | // search in right half 29 | return magicIndex( arr, mid + 1, right ); 30 | } 31 | return -1; 32 | } 33 | 34 | // if elements are not unique then we need to search recursively in left half and right half 35 | // i.e. same as linear searching. 36 | 37 | int main() { 38 | int arr[] = { -40, -20, -1, 1, 2, 3, 5, 7, 9, 12, 13 }; 39 | cout<< magicIndex( arr, 0, 11 ) << endl; 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /4-Trees-and-Graphs/Successor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Write an algorithm to find the "next" node (i.e., in-order successor) 3 | of a given node in a binary search tree. You may assume that each node 4 | has a link to its parent. 5 | */ 6 | 7 | #include 8 | 9 | class Node { 10 | public: 11 | int key; 12 | Node *left; 13 | Node *right; 14 | Node *parent; 15 | }; 16 | 17 | Node * getMin( Node *node ) { 18 | if( node == NULL ) 19 | return NULL; 20 | 21 | while( node->left != NULL ) { 22 | node = node->left; 23 | } 24 | return node; 25 | } 26 | 27 | Node * successor( Node *node ) { 28 | if( node == NULL ) 29 | return NULL; 30 | 31 | /* Found right children, return leftmost node of right subtree */ 32 | if( node->right != NULL ) { 33 | return getMin( node->right ); 34 | } else { 35 | // Traverse upwards from q until we find a node x that we have 36 | // not fully traversed 37 | // i.e. when we move from a left node to its parent 38 | Node *q = node; 39 | Node *p = node->parent; 40 | while( p->left != q && p != NULL ) { 41 | q = p; 42 | p = p->parent; 43 | } 44 | return p; 45 | } 46 | } 47 | 48 | int main() { 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /1-Array-And-String/StringCompression.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a method to perform basic string compression using the counts of 3 | repeated characters. For example, the string aabcccccaaa would become a2b1c5a3. 4 | If the "compressed" string would not become smaller than the original string, 5 | your method should return the original string. 6 | You can assume the string has only uppercase and lowercase letters (a - z). 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | string compressString( string &input ) { 15 | string result = ""; 16 | int count; 17 | int index = -1; 18 | 19 | for( int i = 0; i < input.length(); ){ 20 | count = 1; 21 | while( input[ i ] == input[ i + count ] 22 | && ( i + count <= input.length() ) ) { 23 | count++; 24 | } 25 | i = i + count; 26 | 27 | result += input[ i ]; 28 | result += to_string( count ); 29 | } 30 | 31 | if( result.length() >= input.length() ) 32 | return input; 33 | else 34 | return result; 35 | } 36 | 37 | int main() { 38 | string s1 = "aabcccccaaa"; 39 | cout<< "Original string: " << s1 << endl; 40 | cout<< "Compressed string: " << compressString( s1 ) << endl; 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /1-Array-And-String/URLify.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Write a method to replace all spaces in a string with '%20' You may assume that 3 | * the string has sufficient space at the end to hold the additional characters, and 4 | * that you are given the "true" length of the string. 5 | * 6 | * Input: "Mr John Smith " 13 7 | * Output: "Mr%20John%20Smith" 8 | */ 9 | 10 | #include 11 | 12 | using namespace std; 13 | 14 | string replaceSpaceInString( string &input, int len ) { 15 | int spaceCount = 0; 16 | for( int i = 0; i < len; i++ ) { 17 | if( input[ i ] == ' ' ) 18 | spaceCount++; 19 | } 20 | 21 | int trueLen = len + spaceCount*2; 22 | int index = trueLen - 1; 23 | 24 | for( int i = len - 1; i >= 0; i-- ) { 25 | if( input[ i ] != ' ' ) { 26 | input[ index ] = input[ i ]; 27 | index = index - 1; 28 | } else { 29 | input[ index ] = '0'; 30 | input[ index - 1 ] = '2'; 31 | input[ index - 2 ] = '%'; 32 | index = index - 3; 33 | } 34 | } 35 | return input; 36 | } 37 | 38 | 39 | int main() { 40 | string s = "Mr John Smith "; 41 | cout<< "Original input: " << s << endl; 42 | cout<< "Modified input: " << replaceSpaceInString( s, 13 ) << endl; 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/3-Dominos.txt: -------------------------------------------------------------------------------- 1 | Dominos: 2 | There is an 8x8 chessboard in which two diagonally opposite corners have been cut off. 3 | You are given 31 dominos, and a single domino can cover exactly two squares. Can you use 4 | the 31 dominos to cover the entire board? Prove your answer (by providing an example or 5 | showing why it's impossible). 6 | 7 | Solution: 8 | When we try to lay down dominoes on row 1, which only has 7 squares, we may notice that one 9 | domino must stretch into the row 2. Then, when we try to lay down dominoes onto row 2, again 10 | we need to stretch a domino into row 3. 11 | 12 | For each row we place, we'll always have one domino that needs to poke into the next row. 13 | No matter how many times and ways we try to solve this issue, we won't be able to successfully 14 | lay down all the dominoes. 15 | 16 | Other approach: 17 | The chessboard initially has 32 black and 32 white squares. By removing opposite corners 18 | (which must be the same color), we're left with 30 of one color and 32 of the other color. 19 | Each domino we set on the board will always take up one white and one black square. Therefore, 20 | 31 dominos will take up 31 white squares and 31 black squares exactly. On this board, however, 21 | we must have 30 black squares and 32 white squares. Hence, it is impossible. 22 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/10-Poison.txt: -------------------------------------------------------------------------------- 1 | Poison: 2 | You have 1000 bottles of soda, and exactly one is poisoned. You have latest strips which 3 | can be used to detect poison. A single drop of poison will turn the test strip positive 4 | permanently. You can put any number of drops on a test strip at once and you can reuse a 5 | test strip as many times as you'd like (as long as the results are negative). However, you 6 | can only run tests once per day and it takes seven days to return a result. How would you 7 | figure out the poisoned bottle in as few days as possible? 8 | 9 | Solution: 10 | Optimal Approach (7 days) 11 | Notice what each test strip really means. It's a binary indicator for poisoned or unpoisoned. 12 | Is it possible to map 1000 keys to 10 binary values such that each key is mapped to a unique 13 | configuration of values? Yes, of course. This is what a binary number is. We can take each 14 | bottle number and look at its binary representation. If there's a 1 in the ith digit, then we 15 | will add a drop of this bottle's contents to test strip i. Observe that 2^10 is 1024, so 10 16 | test strips will be enough to handle up to 1024 bottles. 17 | We wait seven days, and then read the results. If test strip i is positive, then set bit i 18 | of the result value. Reading all the test strips will give us the ID of the poisoned bottle. 19 | -------------------------------------------------------------------------------- /17-Hard/2-Shuffle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Shuffle: 3 | Write a method to shuffle a deck of cards. It must be a perfect shuffle-in other words, each 4 | of the 52! permutations of the deck has to be equally likely. Assume that you are given a random 5 | number generator which is perfect. 6 | 7 | Solution: 8 | This is a well-known interview question, and a well known alogorithm. 9 | Let's imagine our n-element array. Suppose it looks like this: 10 | [1] [2] [3] [4] [5] 11 | 12 | Using BaseCase and Build approach, we can ask this question: suppose we had a method shuffle(...) 13 | that worked on n-1 elements. Could we use this to shuffle n elements? 14 | 15 | We would first shuffle the first n-1 elements. Then, we would take the nth element and randomly swap 16 | it with an element in the array. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | using std::vector; 24 | 25 | void shuffle( vector &cards ) { 26 | int randIndex; 27 | int size = cards.size(); 28 | int tmp; 29 | for( int i=0; i < size; ++i ) { 30 | randIndex = rand() % size - i; // 0 to size - i - 1 31 | // swap index randIndex and index 'size - 1 - i' 32 | tmp = cards[ randIndex ]; 33 | cards[ randIndex ] = cards[ i ]; 34 | cards[ i ] = tmp; 35 | } 36 | } 37 | 38 | int main() { 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /17-Hard/9-Kth-Multiple.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Kth Multiple: Design an algorithm to find the kth number such that the only prime factors are 3, 5, 3 | and 7. Note that 3,5, and 7 do not have to be factors, but it should not have any other prime factors. 4 | For example, the first several multiples would be (in order) 1,3, 5, 7, 9, 15, 21. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::queue; 13 | 14 | int getKthMultiple( int x, int y, int z, int k ) { 15 | queue qX, qY, qZ; 16 | qX.push(1); 17 | qX.push(x); 18 | qY.push(y); 19 | qZ.push(z); 20 | int min; 21 | for( int i=0; i < k; i++ ) { 22 | min = qX.front() < qY.front() ? ( qX.front() < qZ.front() ? qX.front() : qZ.front() ) : (qY.front() < qZ.front() ? qY.front() : qZ.front() ); 23 | if( min == qX.front() ) { 24 | qX.pop(); 25 | qX.push( min * x ); 26 | qY.push( min * y ); 27 | qZ.push( min * z ); 28 | } 29 | if( min == qY.front() ) { 30 | qY.pop(); 31 | qY.push( min * y ); 32 | qZ.push( min * z ); 33 | } 34 | if( min == qZ.front() ) { 35 | qZ.pop(); 36 | qZ.push( min * z ); 37 | } 38 | } 39 | return min; 40 | } 41 | 42 | int main() { 43 | int k = 10; 44 | int x = 3, y = 5, z = 7; 45 | cout<< getKthMultiple( x, y, z, 10 ) << endl; 46 | } 47 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/FileSystem/README.md: -------------------------------------------------------------------------------- 1 | ## Data structures used to build file systems 2 | 3 | All file systems are different, so there are a huge number of data structures that actually 4 | get used in file systems. 5 | 6 | Many file systems use some sort of bit vector ( usually referred to as a bitmap ) to track 7 | where certain free blocks are, since they have excellent performance for querying whether 8 | a specific block of disk is in use and (for disks that aren't overwhelmingly full) support 9 | reasonably fast lookups of free blocks. 10 | 11 | Many older file systems ( ext and ext2) stored directory structures using simple linked lists. 12 | Apparently this was actually fast enough for most applications, though some types of applications 13 | that used lots of large directories suffered noticeable performance hits. 14 | 15 | The XFS file system was famous for using B+-trees for just about everything, including directory 16 | structures and its journaling system. 17 | 18 | Microsoft's FAT32 system used a huge array (the file allocation table) that store what files 19 | were stored where and which disk sectors follow one another logically in a file. The main drawback 20 | is that the table had to be set up in advance, so there ended up being upper limits on the sizes of 21 | files that could be stored on the disk. However, the array-based system was pretty easy to implement. -------------------------------------------------------------------------------- /11-Testing/2-Random-Crashes.md: -------------------------------------------------------------------------------- 1 | ## Random Crashes: 2 | You are given the source to an application which crashes when it is run. After 3 | running it ten times in a debugger, you find it never crashes in the same place. The application is 4 | single threaded, and uses only the C standard library. What programming errors could be causing 5 | this crash? How would you test each one? 6 | 7 | ## Solution 8 | we can give some general causes of random crashes. 9 | - **Random Variable:** The application may use some random number or variable component that may not 10 | be fixed for every execution of the program. Examples include user input, a random number generated 11 | by the program, or the time of day. 12 | - **Uninitialized Variable:** The application could have an uninitialized variable which, in some languages, 13 | may cause it to take on an arbitrary value. The values of this variable could result in the code taking a 14 | slightly different path each time. 15 | - **Memory Leak:** The program may have run out of memory. Other culprits are totally random for each run 16 | since it depends on the number of processes running at that particular time. This also includes heap 17 | overflow or corruption of data on the stack. 18 | - **Externel Dependencies:** The program may depend on another application, machine, or resource. If there 19 | are multiple dependencies, the program could crash at any point. -------------------------------------------------------------------------------- /12-C-And-C++/ClassAndInheritance.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | #define NAME_SIZE 50 6 | 7 | class Person { 8 | // By default all members are private 9 | int id; 10 | char name[ NAME_SIZE ]; 11 | 12 | public: 13 | void aboutMe() { 14 | cout<< "I'm a person." << endl; 15 | } 16 | }; 17 | 18 | class Student : public Person { 19 | public: 20 | void aboutMe() { 21 | cout<< "I'm a student" << endl; 22 | } 23 | }; 24 | 25 | int main() { 26 | Student *student = new Student(); 27 | student->aboutMe(); // prints "I'm a student" 28 | 29 | delete student; // Imp! Make sure to delete allocated memory 30 | return 0; 31 | } 32 | 33 | /* Imp points on Constructor and Distructor 34 | 1. The constructor of a class is automatically called upon an object's creation. 35 | 2. If no constructor is defined, the compiler automatically generates one called 36 | the Default Constructor. 37 | 3. Person( int a ) : id(a) { 38 | } 39 | The data member id is assigned before the actual object is created and before the 40 | remainder of the constructor code is called. This approach is necessary when the 41 | fields are constant or class types. 42 | 4. The destructor cleans up upon object deletion and is automatically called when an 43 | object is destroyed. It cannot take an argument as we don't explicitly call a destructor. 44 | */ 45 | -------------------------------------------------------------------------------- /11-Testing/3-Chess-Test.md: -------------------------------------------------------------------------------- 1 | ## Chess Test 2 | We have the following method used in a chess game: boolean canMoveTo( int x, int y). 3 | This method is part of the Piece class and returns whether or not the piece can move 4 | to position (x, y) . Explain how you would test this method. 5 | 6 | ## Solution 7 | Two primary types of testing: extreme case validation (ensuring that the program doesn't 8 | crash on bad input), and general case testing. 9 | 10 | ### Testing Type 1: Extreme Case Validation 11 | We need to ensure that the program handles bad or unusual input gracefully. This means checking the 12 | following conditions: 13 | - Test with negative numbers for x and y 14 | - Test with x larger than the width 15 | - Test with y larger than the height 16 | - Test with a completely full board 17 | - Test with an empty or nearly empty board 18 | - Test with far more white pieces than black 19 | - Test with far more black pieces than white 20 | 21 | ### Testing Type 2: General Testing 22 | There are 6 pieces in chess, so we can test each piece against every other piece, in every possible direction. 23 | This would look something like the below code: 24 | ```python 25 | for each piece a: 26 | for each other type of piece b (6 types + empty space) 27 | for each direction d 28 | Create a board with piece a. 29 | Place piece b in direction d. 30 | Try to move - check return value. 31 | ``` -------------------------------------------------------------------------------- /12-C-And-C++/Shallow-Vs-Deep-Copy.txt: -------------------------------------------------------------------------------- 1 | Shallow Copy vs Deep Copy in C++ 2 | 3 | A shallow copy copies all the member values from one object to another. A deep copy does 4 | all this and also deep copies any pointer objects. 5 | 6 | An example of shallow and deep copy is below. 7 | 8 | _______________________________________________________________________ 9 | class String 10 | { 11 | int size; 12 | char* data; 13 | }; 14 | 15 | String s1( "Ace" ); // s1.size = 3 s1.data=0x0000F000 16 | 17 | String s2 = shallowCopy( s1 ); 18 | // s2.size =3 s2.data = 0X0000F000 19 | 20 | String s3 = deepCopy( s1 ); 21 | // s3.size =3 s3.data = 0x0000F00F 22 | // ( With Ace copied to this location. ) 23 | _______________________________________________________________________ 24 | 25 | Note that shallow copy may cause a lot of programming runtime errors, especially with the 26 | creation and deletion of objects. Shallow copy should be used very carefully and only when 27 | a programmer really understands what he wants to do. In most cases, shallow copy is used when 28 | there is a need to pass information about a complex structure without actual duplication of data. 29 | One must also be careful with destruction of objects in a shallow copy. 30 | 31 | In real life, shallow copy is rarely used. Deep copy should be used in most cases, especially 32 | when the size of the copied structure is small. 33 | -------------------------------------------------------------------------------- /16-Moderate/24-Pairs-with-sum.cpp: -------------------------------------------------------------------------------- 1 | /* Pairs with Sum: 2 | Design an algorithm to find all pairs of integers within an array which sum to a 3 | specified value. 4 | 5 | Sol1: Use hashmap. 6 | Sol2: Sort and find matching pair. 7 | */ 8 | 9 | // g++ 24-Pairs-with-sum.cpp --std=c++14 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | using std::cout; 16 | using std::endl; 17 | using std::vector; 18 | using std::unordered_map; 19 | 20 | void findPairWithSum( vector< int > v, int sum ) { 21 | unordered_map< int, int > ht; 22 | for( auto i : v ) { 23 | // add int in vector to hashmap, also keep their count 24 | if( ht.find( i ) != ht.end() ) { 25 | ht[ i ]++; 26 | } else { 27 | ht[ i ] = 1; 28 | } 29 | } 30 | 31 | for( auto i : v ) { 32 | if( ht.find( sum - i ) != ht.end() ) { 33 | // to handle duplicates decrease count once a key has been considered 34 | // remove if count becomes 0 35 | ht[ i ] -= 1; 36 | ht[ sum - i ] -= 1; 37 | if( ht[ i ] == 0 ) { 38 | ht.erase( i ); 39 | } 40 | if( ht[ sum - i ] == 0 ) { 41 | ht.erase( sum - i ); 42 | } 43 | 44 | cout<< i << " " << sum - i << endl; 45 | } 46 | } 47 | } 48 | 49 | int main() { 50 | vector v = { -1, 14, 1, 13, 5, 6, 3, 9, -3, -2 }; 51 | int target = 10; 52 | findPairWithSum( v, target ); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /16-Moderate/22-Langton-Ant.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Langton's Ant: 3 | An ant is sitting on an infinite grid of white and black squares. It initially faces right. 4 | At each step, it does the following: 5 | (1) At a white square, flip the color of the square, turn 90 degrees right (clockwise), and move forward 6 | one unit. 7 | (2) At a black square, flip the color of the square, turn 90 degrees left (counter-clockwise), and move 8 | forward one unit. 9 | Write a program to simulate the first K moves that the ant makes and print the final board as a grid. 10 | Note that you are not provided with the data structure to represent the grid. This is something you 11 | must design yourself. The only input to your method is K. You should print the final grid and return 12 | nothing. The method signature might be something like void printKMoves (int K) . 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | using std::set; 19 | 20 | class Board { 21 | // If a position is in the set, then the square is 22 | // white. Otherwise, it is black. 23 | set< std::pair > whites; 24 | std::pair topLeft; 25 | std::pair bottomRight; 26 | 27 | public: 28 | Board() { 29 | topLeft = std::make_pair( 0, 0 ); 30 | bottomRight = std::make_pair( 0, 0); 31 | } 32 | 33 | bool isWhite( int x ,int y ) { 34 | } 35 | }; 36 | 37 | int main() { 38 | // TODO: 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /15-Threads-And-Lock/README.md: -------------------------------------------------------------------------------- 1 | ## Deadlocks and Deadlock Prevention 2 | A deadlock is a situation where a thread is waiting for an object lock that another thread holds, and this 3 | second thread is waiting for an object lock that the first thread holds (or an equivalent situation with several 4 | threads). Since each thread is waiting for the other thread to relinquish a lock, they both remain waiting 5 | forever. The threads are said to be deadlocked. 6 | In order for a deadlock to occur, you must have all four of the following conditions met: 7 | - 1. Mutual Exclusion: Only one process can access a resource at a given time. (Or, more accurately, there is 8 | limited access to a resource. A deadlock could also occur if a resource has limited quantity.) 9 | - 2. Hold and Wait: Processes already holding a resource can request additional resources, without relinquishing 10 | their current resources. 11 | - 3. No Preemption: One process cannot forcibly remove another process' resource. 12 | - 4. Circular Wait: Two or more processes form a circular chain where each process is waiting on another 13 | resource in the chain. 14 | 15 | Deadlock prevention entails removing any of the above conditions, but it gets tricky because many of these 16 | conditions are difficult to satisfy. For instance, removing #1 is difficult because many resources can only 17 | be used by one process at a time (e.g., printers). Most deadlock prevention algorithms focus on avoiding 18 | condition #4: circular wait. -------------------------------------------------------------------------------- /16-Moderate/21-Sum-Swap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Sum Swap: 3 | Given two arrays of integers, find a pair of values (one value from each array) that you 4 | can swap to give the two arrays the same sum. 5 | 6 | EXAMPLE 7 | Input:{4, 1, 2, 1, 1, 2} and {3, 6, 3, 3} 8 | Output: {1, 3} 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | using std::cout; 16 | using std::endl; 17 | using std::vector; 18 | using std::unordered_map; 19 | 20 | void findPairWithDiff( vector v1, vector v2, int diff ) { 21 | unordered_map hashMap; 22 | for( auto i : v2 ) { 23 | hashMap[ i ] = true; 24 | } 25 | 26 | for( auto i : v1 ) { 27 | if( hashMap.find( diff - i ) != hashMap.end() ) { 28 | cout<< i << " " << diff - i << endl; 29 | } 30 | } 31 | } 32 | 33 | void sumSwap( vector v1, vector v2 ) { 34 | // 1. Get sum of both vector v1 and v2. 35 | // 2. Find the difference in sum. 36 | // 3. Find a pair v2, v1 whose diff is -sum. 37 | vector::iterator it; 38 | int sumV1 = 0, sumV2 = 0; 39 | for( it = v1.begin(); it != v1.end(); ++it ) { 40 | sumV1 += *it; 41 | } 42 | for( it = v2.begin(); it != v2.end(); ++it ) { 43 | sumV2 += *it; 44 | } 45 | int diff = sumV2 - sumV1; 46 | findPairWithDiff( v1, v2, diff ); 47 | } 48 | 49 | int main() { 50 | vector v1 = { 4, 1, 2, 1, 1, 2 }; 51 | vector v2 = { 3, 6, 3, 3 }; 52 | sumSwap( v1, v2 ); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/7-The-Apocalypse.txt: -------------------------------------------------------------------------------- 1 | The Apocalypse: 2 | In the new post-apocalyptic world, the world queen is desperately concerned 3 | about the birth rate. Therefore, she decrees that all families should ensure 4 | that they have one girl or else they face massive fines. If all families abide 5 | by this policy-that is, they have continue to have children until they have 6 | one girl, at which point they immediately stop-what will the gender ratio of 7 | the new generation be? ( Assume that the odds of someone having a boy or a girl 8 | on any given pregnancy is equal.) Solve this out logically. 9 | 10 | Solution: 11 | Each family will have a sequence of zero or more boys followed by a single girl. 12 | That is, if "G" indicates a girl and "B" indicates a boy, the sequence of children 13 | will look like one of: G, BG, BBG, BBBG, BBBBG and so on. 14 | 15 | P(G) = 1/2. That is, 50% of families will have a girl first. The others will go 16 | on to have more children. 17 | P(BG) = 1/4 Of those who have a second child (which is 50%), 50% of them will 18 | have a girl the next time. 19 | P(BBG) = 1/8 . Of those who have a third child (which is 25%), 50% of them will 20 | have a girl the next time. 21 | And so on. 22 | 23 | We know that every family has exactly one girl. The expected value of the number 24 | of boys is the probability of each sequence multiplied by the number of boys in 25 | that sequence. ~1. 26 | 27 | So, gender ratio is going to be 1:1. 28 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/TowerOfHanio.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Towers of Hanoi: 3 | In the classic problem of the Towers of Hanoi, you have 3 towers and N disks of different 4 | sizes which can slide onto any tower. The puzzle starts with disks sorted in ascending 5 | order of size from top to bottom ( i.e., each disk sits on top of an even larger one ). 6 | You have the following constraints: 7 | (1) Only one disk can be moved at a time. 8 | (2) A disk is slid off the top of one tower onto another tower. 9 | (3) A disk cannot be placed on top of a smaller disk. 10 | 11 | Write a program to move the disks from the first tower to the last using stacks. 12 | */ 13 | 14 | #include 15 | 16 | using std::cout; 17 | using std::endl; 18 | 19 | // Moves all disc from tower 1 to tower 3 20 | void moveDisc( int noOfDisc, int srcTower, int bufferTower, int dstTower ) { 21 | if( noOfDisc <= 0 ) { 22 | return; 23 | } 24 | // move top n-1 from source to buffer, so buffer is new dst 25 | moveDisc( noOfDisc - 1, srcTower, dstTower, bufferTower ); 26 | // move nth disc to destination 27 | cout<< "Moving disc " << noOfDisc << " from tower " << srcTower << " to tower " << dstTower << endl; 28 | // move n-1 discs from buffer to dest tower 29 | moveDisc( noOfDisc - 1, bufferTower, srcTower, dstTower ); 30 | } 31 | 32 | int main() { 33 | int n = 5; 34 | // srcTower = 1 35 | // bufferTower = 2 36 | // dstTower = 3 37 | moveDisc( n, 1, 2, 3 ); 38 | } 39 | -------------------------------------------------------------------------------- /16-Moderate/20-T9.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | T9: 3 | On old cell phones, users typed on a numeric keypad and the phone would provide a list of words 4 | that matched these numbers. Each digit mapped to a set of 0 - 4 letters. Implement an algorithm 5 | to return a list of matching words, given a sequence of digits. You are provided a list of valid words 6 | (provided in whatever data structure you'd like). The mapping is shown in the diagram below: 7 | */ 8 | 9 | // g++ 20-T9.cpp --std=c++14 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | using std::string; 20 | using std::queue; 21 | 22 | void getAllPossibleWords( vector letterMap, string input ) { 23 | queue words; 24 | words.push( "" ); 25 | 26 | for( auto i : input ) { 27 | string map = letterMap[ i - '0' ]; 28 | 29 | int size = words.size(); 30 | for( int j = 0; j < size; ++j ) { 31 | string tmp = words.front(); 32 | words.pop(); 33 | for( auto letter : map ) { 34 | words.push( tmp + letter ); 35 | } 36 | } 37 | } 38 | 39 | while( !words.empty() ) { 40 | cout<< words.front() << endl; 41 | words.pop(); 42 | } 43 | } 44 | 45 | int main() { 46 | vector letterMap = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" }; 47 | string input = "8733"; 48 | getAllPossibleWords( letterMap, input ); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /16-Moderate/5-ZeroesInFactorial.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Factorial Zeros: 3 | Write an algorithm which computes the number of trailing zeros in n factorial. 4 | 5 | Sol: 6 | A simple approach is to compute the factorial, and then count the number of trailing zeros 7 | by continuously dividing by ten. The problem with this though is that the bounds of an int 8 | would be exceeded very quickly. To avoid this issue, we can look at this problem mathematically. 9 | 10 | Consider a factorial like 19! : 11 | 19! = 1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19 12 | 13 | A trailing zero is created with multiples of 10, and multiples of 10 are created with pairs 14 | of 5-multiples and 2-multiples. 15 | 16 | Therefore, to count the number of zeros, we only need to count the pairs of multiples of 5 and 2. 17 | There will always be more multiples of 2 than 5, though, so simply counting the number of multiples 18 | of 5 is sufficient. 19 | 20 | One "gotcha" here is 15 contributes a multiple of 5 (and therefore one trailing zero), while 25 21 | contributes two (because 25 = 5 * 5). 22 | */ 23 | 24 | #include 25 | 26 | using std::cout; 27 | using std::endl; 28 | 29 | int countZerosInFactorial( int N ) { 30 | int zeros = 0; 31 | for( int i=1; i*5 <= N; ++i ) { 32 | int n = i; 33 | while( n >= 5 ) { 34 | ++zeros; 35 | n = n/5; 36 | } 37 | } 38 | return zeros; 39 | } 40 | 41 | int main() { 42 | countZerosInFactorial( 19 ); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/4-Next-Number.cpp: -------------------------------------------------------------------------------- 1 | /* Next Number: 2 | Given a positive integer, print the next smallest and the next largest number that 3 | have the same number of 1 bits in their binary representation. 4 | */ 5 | 6 | #include 7 | using std::cout; 8 | using std::endl; 9 | 10 | int getNext( int n ) { 11 | int tmp = n; 12 | int pos = 0; 13 | 14 | // Step1: Find first "01" in n scanning from right to left 15 | bool one = false; 16 | bool zeroOne = false; 17 | while( pos < 31 ) { 18 | if( ( tmp & 1 ) == 1 ) { 19 | one = true; 20 | } else { 21 | if( one ) { 22 | zeroOne = true; 23 | break; // found first "01" scannig from right to left 24 | } 25 | } 26 | pos++; 27 | tmp = tmp >> 1; 28 | } 29 | 30 | if( not zeroOne ) { 31 | return -1; // this is the highest possible no 32 | } 33 | 34 | // Step2: Replace "01" by "10" 35 | int mask = 0x3 << ( pos - 1 ); // pos can't be less than 1 i.e 0 posn in "01" 36 | n = n ^ mask; 37 | 38 | // Step3: Now shift all bits before "pos - 2" to the right. 39 | tmp = n; 40 | pos = pos - 2; 41 | mask = 0; // new mask to set 1s 42 | while( pos > 0 ) { 43 | if( ( tmp & 1 ) == 1 ) { 44 | mask = mask << 1; 45 | mask = mask | 1; 46 | } 47 | pos--; 48 | tmp = tmp >> 1; 49 | } 50 | 51 | return n | mask; 52 | } 53 | 54 | int main() { 55 | cout << "Next of 15 " << getNext( 15 ) << endl; 56 | cout << "Next of 20 " << getNext( 20 ) << endl; 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /1-Array-And-String/RotateMatirx.cpp: -------------------------------------------------------------------------------- 1 | /* Given an image represented by an NxN matrix, where each pixel in the image is 4 2 | bytes, write a method to rotate the image by 90 degrees. can you do this in place? 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | void printArray( int A[11][11], int n ) { 11 | for( int i = 0; i < n; i++ ) { 12 | for( int j = 0; j < n; j++ ) { 13 | cout << A[i][j] << " "; 14 | } 15 | cout << endl; 16 | } 17 | } 18 | 19 | void rotate90( int ( &A )[11][11], int N ) { 20 | int tmp; 21 | int max = N; 22 | for( int i = 0; i < max; i++ ) { 23 | for( int j = i; j < max - 1; j++ ) { 24 | // Only consider col 0 - maxCol-2, otheriwise corner element will 25 | // get replaced twice. 26 | tmp = A[ i ][ j ]; 27 | A[ i ][ j ] = A[ j ][ max - 1 ]; 28 | A[ j ][ max - 1 ] = A[ max - 1 ][ max - j - 1 ]; 29 | A[ max - 1 ][ max - j - 1 ] = A[ max - j - 1 ][ i ]; 30 | A[ max - j - 1 ][ i ] = tmp; 31 | } 32 | // each time max will reduce by 2 rows and 2 cols 33 | max--; 34 | } 35 | } 36 | 37 | int main() { 38 | int arr[ 11 ][ 11 ]; 39 | int N = 11; 40 | for( int i = 0; i < N; i++ ) { 41 | for( int j = 0; j < N; j++ ) { 42 | arr[i][j] = rand() % 10; 43 | } 44 | } 45 | 46 | cout<< "Original 2-D Array: " << endl; 47 | printArray( arr, N ); 48 | rotate90( arr, N ); 49 | cout<< "90 degree rotated arrat: " << endl; 50 | printArray( arr, N ); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /3-Stacks-And-Queues/StackMin.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | How would you design a stack which, in addition to push and pop, has a function min 4 | which returns the minimum element? Push, pop and min should all operate in 0(1) time. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | class Node{ 13 | private: 14 | int data_; 15 | int min_; 16 | public: 17 | Node( int _data ) : data_( _data ) {} 18 | int data() { return data_; } 19 | void dataIs( int _data ) { data_=_data; } 20 | void minIs( int _min ) { min_ = _min; } 21 | int min() { return min_; } 22 | }; 23 | 24 | class StackWithMinOp{ 25 | private: 26 | stack< Node* > s; 27 | public: 28 | Node * top() { return s.top(); } 29 | void pop() { s.pop(); } 30 | void push( int n ) { 31 | Node * node = new Node( n ); 32 | int currMin = n; 33 | 34 | if( not s.empty() ) { 35 | currMin = s.top()->min(); 36 | if( n < currMin ) { 37 | currMin = n; 38 | } 39 | } 40 | 41 | node->minIs( currMin ); 42 | s.push( node ); 43 | } 44 | int min() { return s.top()->min(); } 45 | }; 46 | 47 | int main() { 48 | StackWithMinOp s; 49 | s.push( 5 ); 50 | cout<< " Min " << s.min() << endl; 51 | s.push( 6 ); 52 | cout<< " Min " << s.min() << endl; 53 | s.push( 3 ); 54 | cout<< " Min " << s.min() << endl; 55 | s.push( 7 ); 56 | cout<< " Min " << s.min() << endl; 57 | s.pop(); 58 | cout<< " Min " << s.min() << endl; 59 | s.pop(); 60 | cout<< " Min " << s.min() << endl; 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/8-Draw-Line.cpp: -------------------------------------------------------------------------------- 1 | /* Draw Line: 2 | A monochrome screen is stored as a single array of bytes, allowing eight consecutive 3 | pixels to be stored in one byte. The screen has width w, where w is divisible by 8 ( 4 | that is, no byte will be split across rows ). The height of the screen, ofcourse, can 5 | be derived from the length of the array and the width. Implement a function that draws 6 | a horizontal line from ( x1, y ) to ( x2, y ). 7 | The method signature should look something like: 8 | 9 | drawLine( byte[] screen, int width, int x1, int x2 , int y ) 10 | */ 11 | 12 | #include 13 | using std::cout; 14 | using std::endl; 15 | 16 | void drawLine( int (&screen)[], int width, int x1, int x2, int y ) { 17 | int start = x1/8; 18 | int startOffset = x1 % 8; 19 | int end = x2/8; 20 | int endOffset = x1 % 8; 21 | 22 | if( start == end ) { 23 | // set bit from startOffset to endOffset 24 | } else { 25 | // set bytes from start + 1 to end - 1 26 | for( int i = start + 1; i < end -1; i++ ) 27 | screen[ i ] = 0xff; 28 | // handle start byte, set bits from startOffset to 7th bit 29 | int mask = 0xff; 30 | while( startOffset ) { 31 | mask = mask << 1; 32 | startOffset--; 33 | } 34 | screen[ start ] = mask; 35 | // handle end byte, set bits from 0th to endOffset 36 | mask = 0xff; 37 | while( endOffset ) { 38 | mask = mask >> 1; 39 | } 40 | screen[ end ] = mask; 41 | } 42 | } 43 | 44 | int main() { 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /16-Moderate/13-Bisect-Squares.cpp: -------------------------------------------------------------------------------- 1 | /* Bisect Squares: 2 | 3 | Given two squares on a two-dimensional plane, find a line that would cut these two squares 4 | in half. Assume that the top and the bottom sides of the square run parallel to the x-axis. 5 | 6 | Sol: A line passing through the center of 2 square cuts both into half. */ 7 | 8 | #include 9 | 10 | class Square { 11 | /* 12 | Square re-presentation 13 | 14 | (x,y+a) ------------- (x+a, y+a) 15 | | | 16 | | | 17 | | | 18 | | | 19 | | | 20 | (x,y) ------------- (x+a, y) */ 21 | double x; 22 | double y; 23 | double edge; 24 | 25 | public: 26 | Square( double x_, double y_, double edge_ ) : x( x_ ), y( y_ ), edge( edge_ ) {} 27 | 28 | std::pair getCenter() { 29 | return std::make_pair( this->x + this->edge/2, this->y + this->edge/2 ); 30 | } 31 | 32 | std::pair getIntersectingLine( Square &s ) { 33 | // TODO: 34 | // check if both circle have same center 35 | std::pair a = this->getCenter(); 36 | std::pair b = s.getCenter(); 37 | 38 | double slope = (a.second - b.second)/(a.first - a.second); 39 | // y = mx + c 40 | // c = y - mx 41 | double intercept = a.second - slope * a.first; 42 | return std::make_pair( slope, intercept ); 43 | } 44 | }; 45 | 46 | int main() { 47 | Square A( 2, 3, 3 ), B( 5, 6, 3 ); 48 | A.getIntersectingLine( B ); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /12-C-And-C++/Aligned_malloc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Write an aligned malloc and free function that supports allocating 3 | memory such that the memory address returned is divisible by a specific 4 | power of two. 5 | 6 | EXAMPLE 7 | align_malloc( 1000, 128) will return a memory address that is a multiple 8 | of 128 and that points to memory of size 1000 bytes. 9 | 10 | aligned_free() will free memory allocated by align_malloc. 11 | */ 12 | 13 | /* 14 | Note: 15 | Typically, with malloc, we do not have control over where the memory is 16 | allocated within the heap. We just get a pointer to a block of memory 17 | which could start at any memory address within the heap. 18 | */ 19 | 20 | #include 21 | 22 | using namespace std; 23 | 24 | void * aligned_malloc( size_t req_size, size_t alignment ) { 25 | size_t size = req_size + // required size 26 | alignment - 1 + // for alignment purpose 27 | sizeof( void * ); // to store address for free operation 28 | 29 | void *p; // Initial block 30 | void *q; // Aligned block inside initial block 31 | 32 | p = (void *) malloc( size ); 33 | if( p == NULL ) 34 | return NULL; 35 | 36 | size_t reminder = (size_t) q % alignment; 37 | q = ( void * ) ( (size_t)p + (size_t)( alignment - reminder ) ); 38 | 39 | // save starting address of initial block at q - 1 location 40 | ((void **) q )[ -1] = p; 41 | return q; 42 | } 43 | 44 | void free( void *p ) { 45 | void *q = ( (void **) p )[ -1 ]; 46 | free( q ); 47 | } 48 | 49 | int main() { 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /1-Array-And-String/CheckPermutation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Given two strings, write a method to decide if one is a permutation of the other. 3 | 4 | Assumption: 5 | ASCII string. 6 | 7 | Ques to ask: 8 | Is case sensitive; 9 | Is white-space significant. 10 | */ 11 | 12 | #include 13 | 14 | using namespace std; 15 | 16 | bool checkPermutation( string string1, string string2 ) { 17 | // Check if the two strings have identical character counts. 18 | if( string1.length() != string2.length() ) { 19 | return false; 20 | } 21 | int charMap[128] = {0}; 22 | for( int i=0; i < string1.length(); i++ ) { 23 | charMap[ string1[ i ] ]++; 24 | } 25 | 26 | for( int i=0; i < string2.length(); i++ ) { 27 | if( charMap[ string2[ i ] ] == 0 ) { 28 | return false; 29 | } 30 | charMap[ string2[ i ] ]--; 31 | } 32 | return true; 33 | } 34 | 35 | bool checkPermutationUsingSorting( string input1, string input2 ) { 36 | sort( input1.begin(), input1.end() ); 37 | sort( input2.begin(), input2.end() ); 38 | if( input1 == input2 ) 39 | return true; 40 | return false; 41 | } 42 | 43 | int main() { 44 | cout<< "Program to check if two strings are permutations of each other" << endl; 45 | string s1 = "hey how are you ?"; 46 | string s2 = "how are uoy yeh ?"; 47 | string s3 = "how are uoy yeh h ?"; 48 | 49 | cout<< checkPermutation( s1, s2 ) << endl; 50 | cout<< checkPermutation( s1, s3 ) << endl; 51 | cout << checkPermutationUsingSorting( s1, s2 ) << endl; 52 | cout << checkPermutationUsingSorting( s1, s3 ) << endl; 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/PermutationWithDups.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Permutations with Dups: 3 | Write a method to compute all permutations of a string whose characters are not 4 | necessarily unique. The list of permutations should not have duplicates. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | using std::cout; 12 | using std::endl; 13 | using std::string; 14 | using std::vector; 15 | 16 | void getAllPermutations( string input ) { 17 | vector< string > currPerm = { input.substr( 0, 1) }; // base case with 1 element [ { 'a' } ] 18 | vector< string > nextPerm; 19 | 20 | for( int i = 1; i < input.length(); i++ ) { 21 | for( auto it = currPerm.begin(); it != currPerm.end(); ++it ) { 22 | // for each permutation 'it' of length i append input[i+1] at all places in 23 | // 'it' to get permutation of length 'i+1' 24 | string s = *it; 25 | for( int j = 0; j <= s.length(); ++j ) { 26 | if( ( j > 0 ) && ( input[ i ] == input[ j - 1 ] ) ) { 27 | // check to see if this element is already duplicate of adjacement element 28 | continue; 29 | } 30 | string tmp = s.substr( 0, j ) + input[ i ] + s.substr( j, s.length() ); 31 | nextPerm.push_back( tmp ); 32 | } 33 | } 34 | currPerm = nextPerm; 35 | nextPerm.clear(); 36 | } 37 | for( auto it = currPerm.begin(); it != currPerm.end(); ++it ) { 38 | cout<< *it << endl; 39 | } 40 | } 41 | 42 | int main() { 43 | string input = "aabcd"; 44 | getAllPermutations( input ); // should print 60 permutations n!/noOfRep! 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/9-100_Lockers.txt: -------------------------------------------------------------------------------- 1 | 100 Lockers: 2 | There are 100 closed lockers in a hallway. A man begins by opening all 100 lockers. 3 | Next, he closes every second locker. Then, on his third pass, he toggles every third 4 | locker (closes it if it is open or opens it if it is closed). This process continues 5 | for 100 passes, such that on each pass i, the man toggles every i th locker. After 6 | his 100th pass in the hallway, in which he toggles only locker #100, how many lockers 7 | are open? 8 | 9 | Solution: 10 | For which rounds is a door toggled (open or closed)? 11 | A door n is toggled once for each factor of n, including itself and 1. That is, door 15 is toggled on rounds 1, 12 | 3,5, and 15. 13 | 14 | When would a door be left open? 15 | A door is left open if the number of factors (which we will call x) is odd. You can think about this by pairing 16 | factors off as an open and a close. If there's one remaining, the door will be open. 17 | 18 | When would x be odd? 19 | The value x is odd if n is a perfect square. Here's why: pair n's factors by their complements. For example, 20 | if n is 36, the factors are (1, 36), (2, 18), (3, 12), (4, 9), (6,6). Note that (6, 6) only contributes one factor, thus 21 | giving n an odd number of factors. 22 | 23 | How many perfect squares are there? 24 | There are 10 perfect squares. You could count them ( 1, 4, 9, 16, 25, 36, 49, 64, 81, 100) or you could simply 25 | realize that you can take the numbers 1 through 10 and square them: 26 | 1*1, 2*2, 3*3, ... , 10*10 27 | 28 | Therefore, there are 10 lockers open at the end of this process. 29 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/StackOfBoxes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Stack of Boxes: 3 | You have a stack of n boxes, with widths Wi heights hi and depths di. 4 | The boxes cannot be rotated and can only be stacked on top of one another if each box 5 | in the stack is strictly larger than the box above it in width, height, and depth. 6 | 7 | Implement a method to compute the height of the tallest possible stack. The height of a 8 | stack is the sum of the heights of each box. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | using std::vector; 15 | 16 | // assume we have sorted boxes on height 17 | int maxHeight( int numBoxes, vector &height, vector &width, vector & depth ) { 18 | int maxHeight[ numBoxes] = { 0 }; 19 | for( int i=0; i< numBoxes; ++i ) { 20 | maxHeight[i] = height[i ]; 21 | } 22 | for( int i=1; i < numBoxes; ++i ) { 23 | int h = 0; 24 | for( int j=0; j < i; ++j ) { 25 | if( height[ i ] > height[ j ] && 26 | width[ i ] > widht[ j ] && 27 | depth[ i ] > depth[ j ] ) { 28 | h = maxHeight[ i ] + maxHeight[ j ]; 29 | } 30 | } 31 | if( h > maxHeight[ i ] ) { 32 | maxHeight[ i ] = h; 33 | } 34 | } 35 | } 36 | 37 | int main() { 38 | int numBoxes = 100; 39 | vector< int > height; 40 | vector< int > width; 41 | vector< int > depth; 42 | for( int i=0; i< numBoxes; i++ ) { 43 | // put some numbers for testing 44 | height.push_back( 0 ); 45 | width.push_back( 0 ); 46 | depth.push_back( 0 ); 47 | } 48 | maxHeight( numBoxes, height, width, depth ); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /16-Moderate/3-Intersection-line-segment.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Intersection: 3 | Given two straight line segments ( represented as a start point and an end point ) 4 | compute the point of intersection, if any. 5 | 6 | Two segments (p1,q1) and (p2,q2) intersect if and only if one of the following two conditions is verified 7 | 8 | General Case: 9 | – (p1, q1, p2) and (p1, q1, q2) have different orientations and 10 | – (p2, q2, p1) and (p2, q2, q1) have different orientations. 11 | 12 | https://www.geeksforgeeks.org/orientation-3-ordered-points/ 13 | */ 14 | 15 | #include 16 | 17 | using std::cout; 18 | using std::endl; 19 | 20 | struct Point { 21 | int x; 22 | int y; 23 | 24 | Point( int _x, int _y ) { 25 | x = _x; 26 | y = _y; 27 | } 28 | }; 29 | 30 | bool checkOrientation( Point p1, Point p2, Point p3, Point p4 ) { 31 | /* Point p1-p2 represent a line; 32 | Point p3-p4 represent another line; */ 33 | int slopeP1P2P3 = ( p2.y - p1.y )*( p3.x - p2.x ) - ( p3.y - p2.y )*( p2.x - p1.x ); 34 | int slopeP1P2P4 = ( p2.y - p1.y )*( p4.x - p2.x ) - ( p4.y - p2.y )*( p2.x - p1.x ); 35 | if( ( slopeP1P2P3 > 0 && slopeP1P2P4 > 0 ) || 36 | ( slopeP1P2P3 < 0 && slopeP1P2P4 < 0) ) { 37 | return false; 38 | } 39 | return true; 40 | } 41 | 42 | 43 | int main() { 44 | Point A( 1, 2 ); 45 | Point B( 3, 4 ); 46 | Point C( 2, 6 ); 47 | Point D( 5, 4 ); 48 | int orie1 = checkOrientation( A, B, C, D ); 49 | int orie2 = checkOrientation( C, D, A, B ); 50 | if( orie1 != orie2 ) { 51 | cout<< "Lines don't intersect" << endl; 52 | } 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /1-Array-And-String/ZeroMatrix.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Write an algorithm such that if an element in an MxN matrix is 0, its entire row and 3 | column are set to O. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | void initMatrix( int (&Arr)[10][10], int N ) { 12 | for( int i=0; i > rows; 31 | set< int, greater > cols; 32 | for( int i=0; i >::iterator it; 42 | for( it=rows.begin(); it != rows.end(); it++ ) { 43 | for( int i=0; i 8 | #include 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::priority_queue; 13 | 14 | class ContinousMedian { 15 | /* 16 | We maintain a constraint that maxHeap.size() >= minHeap; 17 | The size can vary by maximum 1. 18 | */ 19 | priority_queue< double > maxHeap; 20 | priority_queue< double, std::vector, std::greater > minHeap; 21 | 22 | public: 23 | void addRandom( double input ) { 24 | if( maxHeap.empty() ) { 25 | maxHeap.push( input ); 26 | return; 27 | } 28 | 29 | if( maxHeap.size() == minHeap.size() ) { 30 | if( input > maxHeap.top() ) { 31 | minHeap.push( input ); 32 | maxHeap.push( minHeap.top() ); 33 | minHeap.pop(); 34 | } else { 35 | maxHeap.push( input ); 36 | } 37 | } else { 38 | // maxHeap.size() > minHeap() 39 | if( input > maxHeap.top() ) { 40 | minHeap.push( input ); 41 | } else { 42 | maxHeap.push( input ); 43 | minHeap.push( maxHeap.top() ); 44 | maxHeap.pop(); 45 | } 46 | } 47 | } 48 | 49 | double getMedian() { 50 | if( maxHeap.empty() ) { 51 | return 0; 52 | } 53 | if( maxHeap.size() == minHeap.size() ) { 54 | return maxHeap.top(); 55 | } else { 56 | return ( maxHeap.top() + minHeap.top() )/2.0; 57 | } 58 | } 59 | }; 60 | 61 | int main() { 62 | ContinousMedian median; 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /12-C-And-C++/2D-Array-Mem-Alloc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Write a function in C called my2DAlloc which allocates a two-dimensional array. 3 | Minimize the number of calls to malloc and make sure that the memory is accessible 4 | by the notation arr[ i ][ j ]. 5 | */ 6 | 7 | #include 8 | 9 | using namespace std; 10 | 11 | int** my2DAllocVersion1( const int row, const int col ) { 12 | int **arr; 13 | // create a one-dimensional array of pointers 14 | arr = ( int** )malloc( row * sizeof(int*) ); 15 | if( arr == NULL ) return NULL; 16 | 17 | for( int i = 0; i < row; i++ ) { 18 | // for each array index, we create a new one-dimensional array 19 | arr[ i ] = (int*) malloc( sizeof(int) * col ); 20 | } 21 | return arr; 22 | } 23 | 24 | void my2DDeallocVersion1( int **ptr, int row ) { 25 | for( int i = 0; i < row; i++ ) { 26 | free( ptr[ i ] ); 27 | } 28 | free( ptr ); 29 | } 30 | 31 | int** my2DAllocVersion2( int rows, int cols ) { 32 | int header = rows * sizeof(int*); 33 | int data = rows * cols * sizeof(int); 34 | 35 | int** rowptr = (int**)malloc( header + data ); 36 | if (rowptr == NULL) return NULL; 37 | 38 | int* buf = (int*) (rowptr + rows); 39 | for ( int i = 0; i < rows; i++ ) { 40 | rowptr[i] = buf + i * cols; 41 | } 42 | return rowptr; 43 | } 44 | 45 | 46 | int main() { 47 | const int row = 5; 48 | const int col = 6; 49 | int **arr = my2DAllocVersion1( row, col ); 50 | if( arr == NULL ) 51 | exit(1); 52 | arr[0][0] = 10; 53 | 54 | my2DDeallocVersion1( arr, row ); 55 | 56 | int **arr2 = my2DAllocVersion2( row, col ); 57 | arr2[1][1] = 20; 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/8-Egg-Drop-Problem.txt: -------------------------------------------------------------------------------- 1 | The Egg Drop Problem: 2 | There is a building of 100 floors. If an egg drops from the Nth floor or 3 | above, it will break. If it's dropped from any floor below, it will not 4 | break. You're given two eggs. Find N, while minimizing the number of drops 5 | for the worst case. 6 | 7 | Solution: 8 | We observe that, regardless of how we drop Egg 1, Egg 2 must do a linear 9 | search ( from lowest to highest ) between the "breaking floor" and the next 10 | highest non-breaking floor. 11 | 12 | As a first try, suppose we drop an egg from the 10th floor, then the 20th, ...• 13 | If Egg 1 breaks on the first drop (floor 10), then we have at most 10 drops total. 14 | If Egg 1 breaks on the last drop (floor 100), then we have at most 19 drops total 15 | ( floors 10,20, ... ,90, 100, then 91 through 99). 16 | 17 | That's pretty good, but all we've considered is the absolute worst case. We should 18 | do some "load balancing" to make those two cases more even. 19 | 20 | * A perfectly load-balanced system would be one in which Drops (Egg 1) + Drops (Egg 2) is always 21 | the same, regardless of where Egg 1 breaks. 22 | * For that to be the case, since each drop of Egg 1 takes one more step, Egg 2 is allowed one fewer step. 23 | * We must, therefore, reduce the number of steps potentially required by Egg 2 by one drop each time. 24 | * Egg 1 must start at floor X, then go up by X -1 floors, then X - 2, ... , until it gets to 100. 25 | 26 | X + ( X - 1) + ( X - 2 )+ ... +1 = 100 27 | 28 | X = 13.65 29 | X = 14 floor 30 | The number of drops of Egg 1 and Egg 2 always sum to the same thing: 14. 31 | 32 | As in many other maximizing / minimizing problems, the key in this problem is "worst case balancing'. 33 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/PermutationWithoutDup.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | g++ PermutationWithoutDup.cpp -o test --std=c++14 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::string; 12 | using std::vector; 13 | 14 | void getAllPermutations( string input ) { 15 | vector< string > currPerm = { input.substr(0,1) }; // base case 16 | vector< string > nextPerm; 17 | 18 | for( int i = 1; i < input.length(); i++ ) { 19 | for( auto it = currPerm.begin(); it != currPerm.end(); ++it ) { 20 | // for each permuation of size i put input[ i + 1 ] at each position 21 | // thus obtaining permuation of size i+1 22 | string s = *it; 23 | for( int j = 0; j <= s.length(); ++j ) { 24 | string tmp = s.substr( 0, j ) + input[ i ] + s.substr( j, s.length() ); 25 | nextPerm.push_back( tmp ); 26 | } 27 | } 28 | currPerm = nextPerm; 29 | nextPerm.clear(); 30 | } 31 | 32 | // print permutation of size input.length() 33 | for( auto it = currPerm.begin(); it != currPerm.end(); ++it ) { 34 | cout<< *it << endl; 35 | } 36 | } 37 | 38 | void getAllPermutationRecursive( string input, string prefix, int size ) { 39 | if( prefix.length() == size ) { 40 | cout<< prefix << endl; 41 | return; 42 | } 43 | for( int i = 0; i < input.length(); i++ ) { 44 | getAllPermutationRecursive( input.substr( 0, i ) + input.substr( i+1, input.length() ), prefix + input[ i ], size ); 45 | } 46 | } 47 | 48 | int main() { 49 | string input = "abcd"; 50 | getAllPermutations( input ); 51 | cout<< "With Recursive approach" << endl; 52 | getAllPermutationRecursive( input, "", input.length() ); 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /17-Hard/21-Volume-Of-Histogram.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Volume of Histogram: 3 | Imagine a histogram (bar graph). Design an algorithm to compute the 4 | volume of water it could hold if someone poured water across the top. You can assume that each 5 | histogram bar has width 1. 6 | EXAMPLE 7 | Input: {0, 0, 4, 0, 0, 6, 0, 0, 3, 0, 8, 0, 2, 0, 5, 2, 0, 3, 0, 0} 8 | Output: 26 9 | */ 10 | 11 | // g++ 21-Volume-Of-Histogram.cpp --std=c++11 12 | 13 | #include 14 | #include 15 | 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | 20 | struct Bounds { 21 | unsigned int leftMax; 22 | unsigned int rightMax; 23 | Bounds() { 24 | leftMax = 0; 25 | rightMax = 0; 26 | } 27 | 28 | int getMin() { 29 | return leftMax > rightMax ? rightMax: leftMax; 30 | } 31 | }; 32 | 33 | int getVolume( vector arr ) { 34 | unsigned int vol = 0; 35 | vector bound( arr.size() ); 36 | // get max from left side 37 | int max = 0; 38 | for( int i = 0; i < arr.size(); ++i ) { 39 | if( arr[i] > max ) 40 | max = arr[i]; 41 | bound[i].leftMax = max; 42 | } 43 | // get max from right side 44 | max = 0; 45 | for( int i = arr.size() - 1; i >=0; --i ) { 46 | if( arr[i] > max ) 47 | max = arr[i]; 48 | bound[i].rightMax = max; 49 | } 50 | // get volume 51 | for( int i = 0; i < arr.size(); ++i ) { 52 | vol += bound[i].getMin() - arr[i]; 53 | } 54 | return vol; 55 | } 56 | 57 | int main() { 58 | vector arr = {0, 0, 4, 0, 0, 6, 0, 0, 3, 0, 8, 0, 2, 0, 5, 2, 0, 3, 0, 0}; 59 | vector arr1 = {0, 0, 4, 0, 0, 6, 0, 0, 3, 0, 5, 0, 1, 0, 0, 0}; 60 | cout << getVolume( arr ) << endl; 61 | cout << getVolume( arr1 ) << endl; 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /3-Stacks-And-Queues/SortStack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Write a program to sort a stack such that the smallest items are on the top. 3 | You can use an additional temporary stack, but you may not copy the elements 4 | into any other data structure (such as an array). The stack supports the 5 | following operations: push, pop, peek, and isEmpty. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | void printStack( stack s ) { 14 | stack tmp; 15 | while( ! s.empty() ) { 16 | cout<< s.top() << " "; 17 | tmp.push( s.top() ); 18 | s.pop(); 19 | } 20 | cout<< endl; 21 | } 22 | 23 | void sortStack( stack &s ) { 24 | if( s.empty() ) 25 | return; 26 | 27 | // Assume tmpStack is always sorted in reverse order of result 28 | stack tmpStack; 29 | tmpStack.push( s.top() ); 30 | s.pop(); 31 | 32 | int tmp; 33 | while( not s.empty() ) { 34 | // Insert each item from s to tmpStack at appropriate place 35 | if( tmpStack.top() <= s.top() ) { 36 | tmpStack.push( s.top() ); 37 | s.pop(); 38 | } else { 39 | tmp = s.top(); 40 | s.pop(); 41 | // pop item from tmpStack until we hit the rigth spot for tmp 42 | while( tmp < tmpStack.top() && ! tmpStack.empty() ) { 43 | s.push( tmpStack.top() ); 44 | tmpStack.pop(); 45 | } 46 | // push tmp at right location in tmpStack 47 | tmpStack.push( tmp ); 48 | } 49 | } 50 | // tmpStack is reverse sorted stack 51 | printStack( tmpStack ); 52 | } 53 | 54 | int main() { 55 | stack s1; 56 | s1.push( 6 ); 57 | s1.push( 8 ); 58 | s1.push( 4 ); 59 | s1.push( 9 ); 60 | s1.push( 2 ); 61 | 62 | printStack( s1 ); 63 | sortStack( s1 ); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /12-C-And-C++/VirtualFn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | #define NAME_SIZE 50 6 | 7 | class Person { 8 | int id; 9 | char name[ NAME_SIZE ]; 10 | public: 11 | virtual ~Person() { 12 | cout << "Deleting person" << endl; 13 | } 14 | virtual void aboutMe() { 15 | cout<< "I'm a person" << endl; 16 | } 17 | // "addCourse" is a pure virtual function. Person is an 18 | // abstract class and we cannot instantiate it. 19 | virtual bool addCourse( string s ) = 0; 20 | void report() { 21 | cout<< "Person reporting" << endl; 22 | } 23 | }; 24 | 25 | class Student : public Person { 26 | public: 27 | ~Student() { 28 | cout<< "Deleting student" << endl; 29 | } 30 | void aboutMe() { 31 | cout << "I'm a student" << endl; 32 | } 33 | void report() { 34 | cout<< "Student reporting" << endl; 35 | } 36 | bool addCourse( string s ) { 37 | cout<<"Added course " << s << "to student" << endl; 38 | return true; 39 | } 40 | }; 41 | 42 | int main() { 43 | /*commented out because Person is an abstract class because 44 | addCourse is a pure virtual function. Abstract class cannot 45 | be instantiate. 46 | 47 | Person *p1 = new Person(); 48 | p1->aboutMe(); // prints "I'm a person" 49 | p1->report(); // prints "Person reporting" 50 | delete p1; */ 51 | 52 | Person *p2 = new Student(); 53 | p2->aboutMe(); // prints "I'm a student" 54 | p2->report(); // prints "Person reporting" 55 | // This is because the function reporting is resolved at 56 | // compile time, in a mechanism known as "static binding". 57 | delete p2; 58 | 59 | Student *p3 = new Student(); 60 | p3->aboutMe(); // prints "I'm a student" 61 | p3->report(); // prints "Student reporting" 62 | delete p3; 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /16-Moderate/19-pond-size.cpp: -------------------------------------------------------------------------------- 1 | /* Pond Sizes: 2 | You have an integer matrix representing a plot of land, where the value at that location 3 | represents the height above sea level. A value of zero indicates water. A pond is a region 4 | of water connected vertically, horizontally, or diagonally. The size of the pond is the total 5 | number of connected water cells. Write a method to compute the sizes of all ponds in the matrix. 6 | 7 | EXAMPLE 8 | 9 | Input: 10 | 11 | 0 2 1 0 12 | 0 1 0 1 13 | 1 1 0 1 14 | 0 1 0 1 15 | 16 | Output: 2, 4, 1 (in any order) 17 | */ 18 | 19 | // g++ 19-pond-size.cpp --std=c++14 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | using std::cout; 26 | using std::endl; 27 | using std::vector; 28 | using std::set; 29 | 30 | int getSize( vector< vector > &arr, int row, int col ) { 31 | if( row < 0 || col < 0 || row >= arr.size() || col >= arr.size() ) { 32 | return 0; 33 | } 34 | if( arr[ row ][ col ] != 0 ) { 35 | return 0; 36 | } 37 | int size = 1; 38 | arr[ row ][ col ] = -1; 39 | for( int i=-1; i <= 1; i++ ) { 40 | for( int j=-1; j <= 1; j++ ) { 41 | size += getSize( arr, row + i, col + j ); 42 | } 43 | } 44 | return size; 45 | } 46 | 47 | set pondSize( vector< vector > arr ) { 48 | set sizes; 49 | for( int i = 0; i < arr.size(); ++i ) { 50 | for( int j = 0; j < arr[i].size(); ++j ) { 51 | if( arr[ i ][ j ] == 0 ) { 52 | sizes.insert( getSize( arr, i, j ) ); 53 | } 54 | } 55 | } 56 | return sizes; 57 | } 58 | 59 | int main() { 60 | vector< vector< int > > arr = { { 0, 2, 1, 0 }, { 0, 1, 0, 1 }, { 1, 1, 0 ,1 }, { 0, 1, 0, 1 } }; 61 | set< int > res = pondSize( arr ); 62 | for( auto s : res ) { 63 | cout<< s << endl; 64 | } 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/CallCenter/Employee.h: -------------------------------------------------------------------------------- 1 | #include // assert 2 | #include "Call.h" 3 | 4 | // Forward declaration of CallHandler 5 | class CallHandler; 6 | 7 | class Employee { 8 | int employeeId; 9 | Level level; 10 | Call *call; 11 | CallHandler *callHandler; 12 | 13 | ublic: 14 | void setId( int id ) { 15 | employeeId = id; 16 | } 17 | void setLevel( Level level ) { 18 | level = level; 19 | } 20 | void setCall( Call *c ) { 21 | call = c; 22 | } 23 | void setCallHandler( CallHandler *callHandler ) { 24 | callHandler = callHandler; 25 | } 26 | 27 | // check for availability 28 | bool isAvailable() { 29 | return call == NULL; 30 | } 31 | 32 | // Receive a call 33 | void receiveCall( Call *c ) { 34 | assert( call == NULL ); 35 | call = c; 36 | } 37 | 38 | // Disconnect an ongoing call 39 | void disconnectCall() { 40 | delete call; 41 | call = NULL; 42 | } 43 | 44 | // Escalate to higher level 45 | void escalate(); 46 | }; 47 | 48 | /* Respondent */ 49 | class Respondent : public Employee { 50 | public: 51 | Respondent( int id, CallHandler *callHandler ) { 52 | setId( id ); 53 | setLevel( Level::RESPONDENT ); 54 | setCall( NULL ); 55 | setCallHandler( callHandler ); 56 | } 57 | }; 58 | 59 | /* Manager */ 60 | class Manager : public Employee { 61 | public: 62 | Manager( int id, CallHandler *callHandler ) { 63 | setId( id ); 64 | setLevel( Level::MANAGER ); 65 | setCall( NULL ); 66 | setCallHandler( callHandler); 67 | } 68 | }; 69 | 70 | /* Director */ 71 | class Director : public Employee { 72 | public: 73 | Director( int id, CallHandler *callHandler ) { 74 | setId( id ); 75 | setLevel( Level::DIRECTOR ); 76 | setCall( NULL ); 77 | setCallHandler( callHandler); 78 | } 79 | }; 80 | -------------------------------------------------------------------------------- /3-Stacks-And-Queues/QueueUsingStack.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a MyQueue class which implements a queue using two stacks. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | class MyQueue { 11 | private: 12 | stack stackNew; // insert element in new after placing all item in new 13 | stack stackOld; // pop from old after placing all elements in old 14 | 15 | public: 16 | void push( int i ) { 17 | // insert element in new after placing all item in new stack 18 | int item; 19 | while( not stackOld.empty() ) { 20 | item = stackOld.top(); 21 | stackOld.pop(); 22 | stackNew.push( item ); 23 | } 24 | stackNew.push( i ); 25 | } 26 | 27 | void pop() { 28 | int item; 29 | while( not stackNew.empty() ) { 30 | item = stackNew.top(); 31 | stackNew.pop(); 32 | stackOld.push( item ); 33 | } 34 | stackOld.pop(); 35 | } 36 | 37 | int front() { 38 | int item; 39 | while( not stackNew.empty() ) { 40 | item = stackNew.top(); 41 | stackNew.pop(); 42 | stackOld.push( item ); 43 | } 44 | return stackOld.top(); 45 | } 46 | 47 | int size() { 48 | // size of queue 49 | return stackNew.size() + stackOld.size(); 50 | } 51 | }; 52 | 53 | int main() { 54 | MyQueue queue; 55 | queue.push( 1 ); 56 | queue.push( 2 ); 57 | cout<< "Front " << queue.front() << endl; 58 | queue.push( 3 ); 59 | queue.push( 4 ); 60 | cout<< "Front " << queue.front() << endl; 61 | queue.push( 5 ); 62 | cout<< "Front " << queue.front() << endl; 63 | queue.pop(); 64 | cout<< "Front " << queue.front() << endl; 65 | queue.push( 10 ); 66 | cout<< "Front " << queue.front() << endl; 67 | queue.pop(); 68 | queue.pop(); 69 | queue.pop(); 70 | cout<< "Front " << queue.front() << endl; 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /1-Array-And-String/PalindromePermutation.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Given a string, write a function to check if it is a permutation of a palindrome. 3 | * A palindrome is a word or phrase that is the same forwards and backwards. A permutation 4 | * is a rearrangement of letters. The palindrome does not need to be limited to just dictionary words. 5 | * EXAMPLE 6 | * Input: Tact Coa 7 | * Output: True (permutations: "taco cat". "atco cta". etc.) 8 | */ 9 | #include 10 | 11 | using namespace std; 12 | 13 | bool canFormPalindrome( string input ) { 14 | int charFreqCount[ 26 ] = {0}; 15 | 16 | int charCount = 0; 17 | for( int i = 0; i < input.length(); i++ ) { 18 | if( input[ i ] == ' ' ) { 19 | continue; 20 | } 21 | if( 'a' <= input[ i ] && input[ i ] <= 'z' ) { 22 | charFreqCount[ input[ i ] - 'a' ]++; 23 | charCount++; 24 | continue; 25 | } 26 | if( 'A' <= input[ i ] && input[ i ] <= 'Z' ) { 27 | charFreqCount[ input[ i ] - 'A' ]++; 28 | charCount++; 29 | } 30 | } 31 | 32 | int oddCount = 0; 33 | for( int i=0; i < 26; i++ ) { 34 | if( charFreqCount[ i ] % 2 != 0 ) 35 | oddCount++; 36 | } 37 | 38 | if( oddCount == 0 && charCount % 2 == 0 ) { 39 | // when char count is even but oddCount is zero. 40 | return true; 41 | } 42 | 43 | if( charCount % 2 != 0 && oddCount == 1 ) { 44 | return true; 45 | } 46 | return false; 47 | } 48 | 49 | int main() { 50 | cout<< "Program to check if a string can form a palindrome" << endl; 51 | string s1 = "Tact Coa"; 52 | string s2 = "taco cat"; 53 | string s3 = "atco cta"; 54 | string s4 = "atca ct t b"; 55 | 56 | cout<< canFormPalindrome( s1 ) << endl; 57 | cout<< canFormPalindrome( s2 ) << endl; 58 | cout<< canFormPalindrome( s3 ) << endl; 59 | cout<< canFormPalindrome( s4 ) << endl; 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /12-C-And-C++/How-virtual-Function-work.txt: -------------------------------------------------------------------------------- 1 | A virtual function depends on a "vtable" or "Virtual Table'. If any function of a class is declared 2 | to be virtual, a vtable is constructed which stores addresses of the virtual functions of this class. 3 | The compiler also adds a hidden vptr variable in all such classes which points to the vtable of that 4 | class. If a virtual function is not overridden in the derived class, the vtable of the derived class 5 | stores the address of the function in its parent class. The vtable is used to resolve the address of 6 | the function when the virtual function is called. Dynamic binding in C++ is performed through the 7 | vtable mechanism. 8 | 9 | Thus, when we assign the derived class object to the base class pointer, the vptr variable points to 10 | the vtable of the derived class. This assignment ensures that the most derived virtual function gets 11 | called. 12 | 13 | Consider the following code. 14 | 15 | class Shape { 16 | public: 17 | int edge_length; 18 | virtual int circumference () { 19 | cout << "Circumference of Base Class" << endl; 20 | return 0; 21 | } 22 | }; 23 | 24 | class Triangle: public Shape { 25 | public: 26 | int circumference () { 27 | cout << "Circumference of Triangle Class" << endl; 28 | return 3*edge_length; 29 | } 30 | }; 31 | 32 | void main() { 33 | Shape *x = new Shape(); 34 | x->circumference(); // prints "Circumference of Base Class" 35 | 36 | Shape *y = new Triangle(); 37 | y->circumference(); // prints "Circumference of Triangle Class" 38 | } 39 | 40 | In the previous example, circumference is a virtual function in the Shape class, so it becomes virtual 41 | in each of the derived classes ( Triangle, etc ). C++ non-virtual function calls are resolved at compile 42 | time with static binding, while virtual function calls are resolved at runtime with dynamic binding. 43 | -------------------------------------------------------------------------------- /11-Testing/6-Test-An-ATM.md: -------------------------------------------------------------------------------- 1 | ## Test an ATM 2 | How would you test an ATM in a distributed banking system? 3 | 4 | ## Solution 5 | The first thing to do on this question is to clarify assumptions. Ask the following questions: 6 | - Who is going to use the ATM? Answers might be "anyone", or it might be "blind people" or any number 7 | of other answers. 8 | - What are they going to use it for? Answers might be "withdrawing money," "transferring money", 9 | "checking their balance", or many other answers. 10 | - What tools do we have to test? Do we have access to the code, or just to the ATM? 11 | 12 | Remember: a good tester makes sure he knows what he's testing! 13 | 14 | Once we understand what the system looks like, we'll want to break down the problem into different testable 15 | components. These components include: 16 | - Logging in 17 | - Withdrawing money 18 | - Depositing money 19 | - Checking balance 20 | - Transferring money 21 | We would probably want to use a mix of manual and automated testing. 22 | 23 | Manual testing would involve going through the steps above, making sure to check for all the error cases 24 | (low balance, new account, nonexistent account, and so on). 25 | 26 | Automated testing is a bit more complex. We'll want to automate all the standard scenarios, as shown 27 | above, and we also want to look for some very specific issues, such as race conditions. Ideally, we would be 28 | able to set up a closed system with fake accounts and ensure that, even if someone withdraws and deposits 29 | money rapidly from different locations, he never gets money or loses money that he shouldn't. 30 | 31 | Above all, we need to prioritize security and reliability. People's accounts must always be protected, and we 32 | must make sure that money is always properly accounted for. No one wants to unexpectedly lose money! A 33 | good tester understands the system priorities. -------------------------------------------------------------------------------- /2-Linked-Lists/PalindromeLinkList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a function to check if a linked list is a palindrome. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | class Node { 11 | private: 12 | int data_; 13 | Node *next_; 14 | public: 15 | Node( int _data ) : data_( _data ), next_( NULL ) {} 16 | ~Node() { next_ = NULL; } 17 | Node * next() { return this->next_; } 18 | int data() { return data_; } 19 | void dataIs( int _data ) { data_ = _data; } 20 | void nextIs( Node *node ) { this->next_ = node; } 21 | }; 22 | 23 | void addFront( Node **head, int data ) { 24 | Node *newNode = new Node( data ); 25 | newNode->nextIs( *head ); 26 | *head = newNode; 27 | } 28 | 29 | void printLL( Node *node ) { 30 | while( node != NULL ) { 31 | cout<< node->data() << "->"; 32 | node = node->next(); 33 | } 34 | cout << endl; 35 | } 36 | 37 | bool checkPalindrome( Node * node ) { 38 | stack< int > s; 39 | Node *curr = node; 40 | while( curr != NULL ) { 41 | s.push( curr->data() ); 42 | curr = curr->next(); 43 | } 44 | 45 | curr = node; 46 | while( s.empty() == false && curr != NULL ) { 47 | if( s.top() != curr->data() ) 48 | return false; 49 | s.pop(); 50 | curr = curr->next(); 51 | } 52 | 53 | if( curr == NULL && s.empty() ) 54 | return true; 55 | 56 | return false; 57 | } 58 | 59 | int main() { 60 | Node *head = NULL; 61 | 62 | // create a LL 63 | addFront( &head, 8 ); 64 | addFront( &head, 2 ); 65 | addFront( &head, 4 ); 66 | addFront( &head, 6 ); 67 | addFront( &head, 4 ); 68 | addFront( &head, 2 ); 69 | addFront( &head, 8 ); 70 | 71 | // print Linked List 72 | printLL( head ); 73 | 74 | cout<< " Is palindrome: " << checkPalindrome( head ) << endl; 75 | addFront( &head, 9 ); 76 | cout<< " Is palindrome: " << checkPalindrome( head ) << endl; 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /16-Moderate/2-Word-Frequencies.cpp: -------------------------------------------------------------------------------- 1 | /* Word Frequencies: 2 | Design a method to find the frequency of occurrences of any given word in a 3 | book. What if we were running this algorithm multiple times? */ 4 | 5 | // Compile using: g++ 2-Word-Frequencies.cpp --std=c++14 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using std::string; 14 | using std::vector; 15 | using std::cout; 16 | using std::endl; 17 | using std::map; 18 | 19 | /*If the fequencies have to searched for only one time.*/ 20 | int wordFrequency( string word, const vector book ) { 21 | int freq = 0; 22 | for( auto s : book ) { 23 | std::transform( s.begin(), s.end(), s.begin(), tolower ); 24 | if( s == word ) { 25 | ++freq; 26 | } 27 | } 28 | return freq; 29 | } 30 | 31 | 32 | /* Repetitive Queries*/ 33 | map< string, int > createWordFreqTable( const vector book ) { 34 | map< string, int> wordFreqTable; 35 | for( auto s : book ) { 36 | std::transform( s.begin(), s.end(), s.begin(), tolower ); 37 | if ( wordFreqTable.find( s ) != wordFreqTable.end() ) { 38 | ++wordFreqTable[s]; 39 | } else { 40 | wordFreqTable[s] = 1; 41 | } 42 | } 43 | return wordFreqTable; 44 | } 45 | 46 | int getFreqency( map< string, int> &wordFreqTable, string word ) { 47 | if( word == "" ) 48 | return -1; 49 | 50 | std::transform( word.begin(), word.end(), word.begin(), tolower ); 51 | int count = 0; 52 | if( wordFreqTable.find( word ) != wordFreqTable.end() ) { 53 | count = wordFreqTable[ word ]; 54 | } 55 | return count; 56 | } 57 | 58 | int main() { 59 | vector< string> s = { "Convert", "to", "Lower", "TO" }; 60 | cout << wordFrequency( "to", s ) << endl; 61 | map< string, int > wordFreqTable = createWordFreqTable( s ); 62 | cout<< getFreqency( wordFreqTable, "to" ) << endl; 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /2-Linked-Lists/KthToLast.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Implement an algorithm to find the kth to last element of a singly linked list. 3 | */ 4 | 5 | #include 6 | 7 | using namespace std; 8 | 9 | class Node { 10 | private: 11 | int data_; 12 | Node *next_; 13 | public: 14 | Node( int _data ) : data_( _data ), next_( NULL ) {} 15 | ~Node() { 16 | next_ = NULL; 17 | } 18 | Node * next() { return this->next_; } 19 | int data() { return data_; } 20 | void nextIs( Node *node ) { this->next_ = node; } 21 | }; 22 | 23 | void addFront( Node *head, int data ) { 24 | Node *newNode = new Node( data ); 25 | newNode->nextIs( head->next() ); 26 | head->nextIs( newNode ); 27 | } 28 | 29 | void printLL( Node *node ) { 30 | while( node != NULL ) { 31 | cout<< node->data() << "->"; 32 | node = node->next(); 33 | } 34 | cout << endl; 35 | } 36 | 37 | Node* kthToLast( Node* head, int k ) { 38 | int i = k; 39 | Node *runner1 = head; 40 | while( i > 0 && runner1 != NULL ) { 41 | // move runner1 k steps ahead 42 | runner1 = runner1->next(); 43 | i--; 44 | } 45 | Node *runner2 = head; 46 | while( runner1->next() != NULL ) { 47 | // when runner 1 reach end, runner 2 would have reached last - kth. 48 | runner1 = runner1->next(); 49 | runner2 = runner2->next(); 50 | } 51 | return runner2; 52 | } 53 | 54 | int main() { 55 | // keep head as a dummy Node 56 | Node *head = new Node( -1 ); 57 | 58 | // create a LL 59 | addFront( head, 10 ); 60 | addFront( head, 12 ); 61 | addFront( head, 14 ); 62 | addFront( head, 16 ); 63 | addFront( head, 10 ); 64 | addFront( head, 14 ); 65 | addFront( head, 18 ); 66 | addFront( head, 10 ); 67 | 68 | // print Linked List 69 | printLL( head->next() ); 70 | 71 | cout<< " 2nd to last " << kthToLast( head->next(), 2 )->data() << endl; 72 | cout<< " 4nd to last " << kthToLast( head->next(), 4 )->data() << endl; 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /17-Hard/14-Smallest-K-in-Array.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Smallest K: 3 | Design an algorithm to find the smallest K numbers in an array. 4 | 5 | Solution: 6 | sorting, max heap, and selection rank. 7 | 8 | Max Heap: 9 | We first create a max heap (largest element at the top) for the first million numbers. 10 | Then, we traverse through the list. On each element, if it's smaller than the root, we 11 | insert it into the heap and delete the largest element (which will be the root). O( n logm ) 12 | 13 | Selection Rank Algorithm (if elements are unique) 14 | Selection Rank is a well-known algorithm in computer science to find the ith smallest 15 | (or largest) element in an array in linear time. If the elements are unique, you can find 16 | the ith smallest element in expected O(n) time. The basic algorithm operates like this: 17 | 1. Pick a random element in the array and use it as a "pivot", Partition elements around the 18 | pivot, keeping track of the number of elements on the left side of the partition. 19 | 2. If there are exactly i elements on the left, then you just return the biggest element on the left. 20 | 3. If the left side is bigger than i, repeat the algorithm on just the left part of the array. 21 | 4. If the left side is smaller than i, repeat the algorithm on the right, but look for the element 22 | with rank i - leftSize. 23 | */ 24 | 25 | // g++ 14-Smallest-K-in-Array.cpp --std=c++11 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | using std::cout; 32 | using std::endl; 33 | using std::priority_queue; 34 | using std::vector; 35 | 36 | priority_queue kSmallest( vector input, int k ) { 37 | priority_queue heap; 38 | for( auto v : input ) { 39 | if( heap.size() < k ) { 40 | heap.push( v ); 41 | } else if( heap.top() < v ) { 42 | heap.push( v ); 43 | heap.pop(); 44 | } 45 | } 46 | return heap; 47 | } 48 | 49 | int main() { 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /2-Linked-Lists/DeleteMiddleNode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Implement an algorithm to delete a node in the middle (ie. any node but 3 | the first and last node, not necessarily the exact middle) of a singly linked 4 | list, given only access to that node. 5 | 6 | EXAMPLE 7 | Input: The node c from the linked list a->b->c->d->e->f 8 | Result: Nothing is returned, but the new linked list looks like a->b->d->e->f 9 | */ 10 | 11 | #include 12 | 13 | using namespace std; 14 | 15 | class Node { 16 | private: 17 | int data_; 18 | Node *next_; 19 | public: 20 | Node( int _data ) : data_( _data ), next_( NULL ) {} 21 | ~Node() { next_ = NULL; } 22 | Node * next() { return this->next_; } 23 | int data() { return data_; } 24 | void dataIs( int _data ) { data_ = _data; } 25 | void nextIs( Node *node ) { this->next_ = node; } 26 | }; 27 | 28 | void addFront( Node *head, int data ) { 29 | Node *newNode = new Node( data ); 30 | newNode->nextIs( head->next() ); 31 | head->nextIs( newNode ); 32 | } 33 | 34 | void printLL( Node *node ) { 35 | while( node != NULL ) { 36 | cout<< node->data() << "->"; 37 | node = node->next(); 38 | } 39 | cout << endl; 40 | } 41 | 42 | void deleteNode( Node *node ) { 43 | // copy the data from the next node over to the current node, 44 | // and then to delete the next node. 45 | 46 | Node *curr = node->next(); 47 | node->dataIs( ( node->next() )->data() ); 48 | node->nextIs( curr->next() ); 49 | delete curr; 50 | } 51 | 52 | int main() { 53 | // keep head as a dummy Node 54 | Node *head = new Node( -1 ); 55 | 56 | // create a LL 57 | addFront( head, 10 ); 58 | addFront( head, 12 ); 59 | addFront( head, 14 ); 60 | addFront( head, 16 ); 61 | addFront( head, 10 ); 62 | addFront( head, 14 ); 63 | addFront( head, 18 ); 64 | addFront( head, 10 ); 65 | 66 | // print Linked List 67 | printLL( head->next() ); 68 | deleteNode( ( head->next() )->next() ); 69 | 70 | printLL( head->next() ); 71 | 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /5-Bit-Manipulation/3-Flip-Bit-To-Win.cpp: -------------------------------------------------------------------------------- 1 | // compile using 'g++ 3-Flip-Bit-To-Win.cpp -o 3-Flip-Bit-To-Win --std=c++14' 2 | 3 | /* Flip Bit to Win: 4 | You have an integer and you can flip exactly one bit from a 0 to a 1. Write code to 5 | find the length of the longest sequence of 1 s you could create. 6 | EXAMPLE 7 | Input: 1775 ( or: 11011101111 ) 8 | Output: 8 */ 9 | 10 | #include 11 | using std::cout; 12 | using std::endl; 13 | using std::pair; 14 | using std::make_pair; 15 | 16 | #include 17 | using std::vector; 18 | 19 | int longestSequestOf1s( int n ) { 20 | // Step 1: Convert integer n into an array that reflects the lengths of the 21 | // Os and 1 s sequences. 22 | 23 | int tmp = n; 24 | int len = 0; 25 | vector< pair< int, int > > lengthOfSubSeq; 26 | 27 | int zeros = 0; 28 | int ones = 0; 29 | while( len < 32 ) { 30 | if( ( tmp & 1 ) == 1 ) { 31 | if( zeros != 0 ) { 32 | lengthOfSubSeq.push_back( make_pair( 0, zeros ) ); 33 | zeros = 0; 34 | } 35 | ones += 1; 36 | } else { 37 | if( ones != 0 ) { 38 | lengthOfSubSeq.push_back( make_pair( 1, ones ) ); 39 | ones = 0; 40 | } 41 | zeros += 1; 42 | } 43 | len++; 44 | tmp = tmp >> 1; 45 | } 46 | 47 | if( zeros ) 48 | lengthOfSubSeq.push_back( make_pair( 0, zeros ) ); 49 | else 50 | lengthOfSubSeq.push_back( make_pair( 0, ones ) ); 51 | 52 | 53 | // step2 : Get the max seq we can get by flipping one zero to 1. 54 | int prev = 0; 55 | int max1s = 0; 56 | for( pair xy : lengthOfSubSeq ) { 57 | if( xy.first == 1 ) { 58 | if( max1s < prev + xy.second ) 59 | max1s = prev + xy.second; 60 | prev = xy.second; 61 | } else { 62 | if( xy.second != 1 ) { 63 | prev = 0; // set prev to 0 if seq is 0 length is more than 1. 64 | } else { 65 | prev = prev + 1; 66 | } 67 | } 68 | } 69 | return max1s; 70 | } 71 | 72 | int main() { 73 | cout << longestSequestOf1s( 1775 ) << endl; 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /12-C-And-C++/1-Last-K-Lines.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Write a method to print the last K lines of an input file using C++. 3 | 4 | Note: 5 | C++ provides the following classes to perform output and input of 6 | characters to/from files: 7 | 8 | ofstream: Stream class to write on files. 9 | ifstream: Stream class to read from files. 10 | fstream: Stream class to both read and write from/to files. 11 | 12 | These classes are derived directly or indirectly from the classes 13 | istream and ostream. We have already used objects whose types were 14 | these classes: cin is an object of class istream and cout is an object 15 | of class ostream. Therefore, we have already been using classes that are 16 | related to our file streams. And in fact, we can use our file streams 17 | the same way we are already used to use cin and cout, with the only 18 | difference that we have to associate these streams with physical files. 19 | Let's see an example: 20 | 21 | // basic file operations 22 | #include 23 | #include 24 | using namespace std; 25 | 26 | int main () { 27 | ofstream myfile; 28 | myfile.open ("example.txt"); 29 | myfile << "Writing this to a file.\n"; 30 | myfile.close(); 31 | return 0; 32 | } 33 | */ 34 | 35 | #include 36 | #include 37 | 38 | using namespace std; 39 | 40 | int main() { 41 | char *filename = "text.txt"; 42 | const int k = 10; // last 10 lines 43 | string line[k]; // circular array to hold 10 lines 44 | int size = 0; 45 | 46 | ifstream infile; 47 | infile.open( filename ); 48 | 49 | /* Read file line by line into circular array */ 50 | while( infile.peek() != EOF ) { 51 | getline( infile, line[ size % k ] ); 52 | size++; 53 | } 54 | infile.close(); 55 | 56 | // compute start of circular array, and size of it 57 | int start = size > k ? ( size % k ) : 0; 58 | int count = min( k, size ); 59 | 60 | for( int i = 0; i < count; i++ ) { 61 | cout<< line[ ( start + i ) % k ] << endl; 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /16-Moderate/12-XML-Encoding.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | XML Encoding: Since XML is very verbose, you are given a way of encoding it where each tag gets 3 | mapped to a pre-defined integer value. The language/grammar is as follows: 4 | Element --> Tag Attributes END Children END 5 | Attribute --> Tag Value 6 | END --> 0 7 | Tag --> some predefined mapping to int 8 | Value --> string value 9 | 10 | For example, the following XML might be converted into the compressed string below (assuming a 11 | mapping of family -> 1, person -> 2, firstName -> 3, lastName -> 4, state -> 5). 12 | 13 | 14 | Some Message 15 | 16 | Becomes: 17 | 1 4 McDowell 5 CA 0 2 3 Gayle 0 Some Message 0 0 18 | 19 | Write code to print the encoded version of an XML element (passed in Element and Attribute 20 | objects). 21 | */ 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | using std::cout; 28 | using std::endl; 29 | using std::string; 30 | using std::map; 31 | 32 | class XMLEncode { 33 | map< string, string > encoding; 34 | 35 | queue parseXML( string xml ) { 36 | // 37 | } 38 | 39 | public: 40 | XMLEncode() { 41 | encoding[ ">" ] = "0"; 42 | encoding[ "<" ] = ""; 43 | encoding[ "=" ] = ""; 44 | } 45 | 46 | void addEncoding( string key, string val ) { 47 | encoding[ key ] = val; 48 | } 49 | 50 | string encode( string xmlStr ) { 51 | string encodedStr; 52 | queue< string > tokens; 53 | return encodedStr; 54 | } 55 | }; 56 | 57 | int main() { 58 | string xmlStr = "Some Message"; 59 | 60 | XMLEncode encoder; 61 | encoder.addEncoding( "family", "1" ); 62 | encoder.addEncoding( "person", "2" ); 63 | encoder.addEncoding( "firstName", "3" ); 64 | encoder.addEncoding( "lastName", "4" ); 65 | encoder.addEncoding( "state", "5" ); 66 | 67 | encoder.encode( xmlStr ); 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /12-C-And-C++/Volatile-In-C++.txt: -------------------------------------------------------------------------------- 1 | Significance of the keyword "volatile" in C 2 | 3 | The keyword volatile informs the compiler that the value of variable it is applied to can 4 | change from the outside, without any update done by the code. This may be done by the operating 5 | system, the hardware, or another thread. Because the value can change unexpectedly, the 6 | compiler will therefore reload the value each time from memory. 7 | 8 | A volatile integer can be declared by either of the following statements: 9 | int volatile x; 10 | volatile int x; 11 | 12 | To declare a pointer to a volatile integer, we do the following: 13 | volatile int * x; 14 | int volatile * x; 15 | 16 | A volatile pointer to non-volatile data is rare, but can be done. 17 | int * volatile x; 18 | 19 | If you wanted to declare a volatile variable pointer for volatile memory ( both pointer address 20 | and memory contained are volatile ), you would do the following: 21 | int volatile * volatile x; 22 | 23 | Volatile variables are not optimized, which can be very useful. Imagine this function: 24 | 25 | int opt = 1; 26 | void Fn(void) { 27 | start: 28 | if (opt == 1) goto start; 29 | else break; 30 | } 31 | 32 | At first glance, our code appears to loop infinitely. The compiler may try to optimize it to: 33 | 34 | void Fn(void) { 35 | start: 36 | int opt = 1; 37 | if (true) 38 | goto start; 39 | } 40 | 41 | This becomes an infinite loop. However, an external operation might write 'O' to the location 42 | of variable opt, thus breaking the loop. 43 | 44 | To prevent the compiler from performing such optimization, we want to signal that another element 45 | of the system could change the variable. We do this using the volatile keyword, as shown below. 46 | 47 | volatile int opt = 1; 48 | void Fn(void) { 49 | start: 50 | if (opt == 1) goto start; 51 | else break; 52 | } 53 | 54 | Volatile variables are also useful when multi-threaded programs have global variables and any 55 | thread can modify these shared variables. We may not want optimization on these variables. 56 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/Coins.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Coins: 3 | Given an infinite number of quarters (25 cents), dimes (10 cents), nickels (5 cents), 4 | and pennies (1 cent), write code to calculate the number of ways of representing n cents. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::vector; 13 | 14 | int getChangeWays( int amount, vector< int > & denom, int index ) { 15 | if( index >= denom.size() - 1 ) return 1; // last denom 16 | int denomAmount = denom[ index]; 17 | int noOfWays = 0; 18 | for( int i = 0; i * denomAmount <= amount; i++ ) { 19 | int amountRem = amount - i * denomAmount; 20 | noOfWays += getChangeWays( amountRem, denom, index + 1 ); 21 | } 22 | return noOfWays; 23 | } 24 | 25 | int makeChange( int amount, vector< int > & denom, int index, 26 | vector< vector< int > > &map ) { 27 | if( index >= denom.size() - 1 ) 28 | return 1; 29 | if( map[ amount][index] > 0 ) 30 | return map[ amount ][index]; 31 | int denomAmount = denom[ index]; 32 | int noOfWays = 0; 33 | for( int i = 0; i * denomAmount <= amount; i++ ) { 34 | int amountRem = amount - i * denomAmount; 35 | noOfWays += makeChange( amountRem, denom, index + 1, map ); 36 | } 37 | map[ amount ][ index ] = noOfWays; 38 | return noOfWays; 39 | } 40 | 41 | int getChangeWaysV1( int amount, vector< int > &denom, int index ) { 42 | vector< vector< int > > map; 43 | for( int i = 0; i <= amount; i++ ) { 44 | map.push_back( { 0, 0, 0, 0 } ); 45 | } 46 | return makeChange( amount, denom, index, map ); 47 | } 48 | 49 | int main() { 50 | int n = 5; 51 | vector< int > denom = { 25, 10, 5, 1 }; 52 | cout<< getChangeWays( n, denom, 0 ) << endl; 53 | cout<< getChangeWaysV1( n, denom, 0 ) << endl; 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /4-Trees-and-Graphs/CheckSubTree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Check Subtree: 3 | T1 and T2 are two very large binary trees, with T1 much bigger than T2. Create an 4 | algorithm to determine if T2 is a subtree of T1. 5 | A tree T2 is a subtree of T1 if there exists a node n in T1 such that the subtree 6 | of n is identical to T2 . That is, if you cut off the tree at node n, the two trees 7 | would be identical. 8 | 9 | Approach 1: 10 | Take pre-order traveral of T1 and T2. In pre-order traversal all null nodes have to 11 | be marked with X so that trees are unique. 12 | Now look for T2 pre-order traversal string in T1 pre-order traversal string. 13 | 14 | Approach 2: 15 | Traverse larger tree, each time you found the root of smaller tree in larger tree. 16 | Call treeMatch function. 17 | We do not actually call matchTree on every node in n. Rather, we call it k times, 18 | where k is the number of occurrences of T2's root in T1. The runtime is closer to O( n + km) . 19 | */ 20 | 21 | #include 22 | 23 | class TreeNode { 24 | public: 25 | TreeNode( int _key ) : left( NULL ), right( NULL ) {} 26 | 27 | int key; 28 | TreeNode *left; 29 | TreeNode *right; 30 | }; 31 | 32 | bool matchTrees( TreeNode *t1, TreeNode *t2 ) { 33 | if( t1 == NULL && t2 == NULL ) { 34 | return true; 35 | } else if( t1 == NULL || t2 == NULL ) { 36 | return false; 37 | } else if( t1->key != t2->key ) { 38 | return false; 39 | } else { 40 | return matchTrees( t1->left, t2->left ) && matchTrees( t1->right, t2->right ); 41 | } 42 | } 43 | 44 | bool isSubTreeUtil( TreeNode *t1, TreeNode *t2 ) { 45 | if( t1 == NULL ) 46 | return false; 47 | if( t1->key == t2->key ) { 48 | return matchTrees( t1, t2 ); 49 | } 50 | return isSubTreeUtil( t1->left, t2 ) || isSubTreeUtil( t1->right, t2 ); 51 | } 52 | 53 | bool isSubTree( TreeNode *t1, TreeNode *t2 ) { 54 | if( t2 == NULL ) { 55 | return true; // subtree is empty 56 | } 57 | return isSubTreeUtil( t1, t2 ); 58 | } 59 | 60 | using namespace std; 61 | 62 | int main() { 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /2-Linked-Lists/RemoveDups.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Write code to remove duplicates from an unsorted linked list. 3 | * FOLLOW UP 4 | * How would you solve this problem if a temporary buffer is not allowed? 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | class Node { 13 | private: 14 | int data_; 15 | Node *next_; 16 | public: 17 | Node( int _data ) : data_( _data ), next_( NULL ) {} 18 | ~Node() { 19 | next_ = NULL; 20 | } 21 | Node * next() { return this->next_; } 22 | int data() { return data_; } 23 | void nextIs( Node *node ) { this->next_ = node; } 24 | }; 25 | 26 | void addFront( Node *head, int data ) { 27 | Node *newNode = new Node( data ); 28 | newNode->nextIs( head->next() ); 29 | head->nextIs( newNode ); 30 | } 31 | 32 | void printLL( Node *node ) { 33 | while( node != NULL ) { 34 | cout<< node->data() << "->"; 35 | node = node->next(); 36 | } 37 | cout << endl; 38 | } 39 | 40 | void removeDups( Node *node ) { 41 | set< int > keySet; 42 | Node *currNode = node; 43 | Node *prev = NULL; 44 | while( currNode != NULL ) { 45 | if( keySet.count( currNode->data() ) == 0 ) { 46 | // key not found, insert key in set 47 | keySet.insert( currNode->data() ); 48 | } else { 49 | // key found, remove currNode 50 | cout<< "Deleting " << currNode->data() << endl; 51 | prev->nextIs( currNode->next() ); 52 | delete currNode; 53 | currNode = prev; 54 | } 55 | prev = currNode; 56 | currNode = currNode->next(); 57 | } 58 | } 59 | 60 | int main() { 61 | // keep head as a dummy Node 62 | Node *head = new Node( -1 ); 63 | 64 | // create a LL with some duplicate entries 65 | addFront( head, 10 ); 66 | addFront( head, 12 ); 67 | addFront( head, 14 ); 68 | addFront( head, 16 ); 69 | addFront( head, 10 ); 70 | addFront( head, 14 ); 71 | addFront( head, 18 ); 72 | addFront( head, 10 ); 73 | 74 | // print Linked List 75 | printLL( head->next() ); 76 | 77 | removeDups( head->next() ); 78 | 79 | printLL( head->next() ); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /7-Object-Oriented-Design/CallCenter/CallHandler.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Compile using 'g++ CallHandler.cpp -o CallHandler --std=c++11' 3 | */ 4 | 5 | #include // std::list 6 | #include // std::queue 7 | 8 | #include "Employee.h" 9 | 10 | using std::list; 11 | using std::queue; 12 | 13 | class CallHandler { 14 | list< Director * > directors; 15 | list< Manager * > managers; 16 | list< Respondent * > respondents; 17 | queue< Call * > callQueue; 18 | 19 | public: 20 | CallHandler( int numRespondents, int numManagers, 21 | int numDirectors ) { 22 | for( int i = 0; i < numRespondents; i++ ) { 23 | respondents.push_back( new Respondent( i, this ) ) ; 24 | } 25 | for( int i = 0; i < numManagers; i++ ) { 26 | managers.push_back( new Manager( i, this ) ); 27 | } 28 | for( int i = 0; i < numDirectors; i++ ) { 29 | directors.push_back( new Director( i, this ) ); 30 | } 31 | } 32 | 33 | void putCallOnQueue( Call *c ) { 34 | callQueue.push( c ); 35 | } 36 | 37 | void dispatchCall( string phoneNo ) { 38 | Call *c = new Call( phoneNo ); 39 | callQueue.push( c ); 40 | handleCall(); 41 | } 42 | 43 | void handleCall() { 44 | if( callQueue.empty() ) { 45 | return; 46 | } 47 | Call *call = callQueue.front(); 48 | // TODO 49 | // check rank of call and find a free employee of that level 50 | // and assign call to that emmployee 51 | callQueue.pop(); 52 | if( !callQueue.empty() ) { 53 | handleCall(); 54 | } 55 | } 56 | }; 57 | 58 | // We need to define this here since callHandler is a forward declaration 59 | // in Employee Method and it access it's member fn 60 | void Employee::escalate() { 61 | if( call->getLevel() == Level::RESPONDENT ) { 62 | call->setLevel( Level::MANAGER ); 63 | } else if ( call->getLevel() == Level::MANAGER ) { 64 | call->setLevel( Level::DIRECTOR ); 65 | } 66 | callHandler->putCallOnQueue( call ); 67 | call = NULL; 68 | } 69 | 70 | int main() { 71 | CallHandler *callHandler = new CallHandler( 20, 4, 2 ); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/RobotInAGrid.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Robot in a Grid: 3 | Imagine a robot sitting on the upper left corner of grid with r rows and c columns. 4 | The robot can only move in two directions, right and down, but certain cells are 5 | "off limits" such that the robot cannot step on them. Design an algorithm to find 6 | a path for the robot from the top left to the bottom right. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | using std::cout; 14 | using std::endl; 15 | using std::vector; 16 | using std::pair; 17 | using std::set; 18 | using std::make_pair; 19 | 20 | int numRow = 10; 21 | int numCol = 10; 22 | bool arr[ 10 ][ 10 ]; 23 | 24 | bool findPath( int rowNo, int colNo ) { 25 | if( !arr[rowNo][colNo] ) { 26 | return false; 27 | } 28 | if( rowNo >= numRow || 29 | colNo >= numCol ) { 30 | return false; 31 | } 32 | if( ( rowNo == numRow - 1 ) && 33 | ( colNo == numCol - 1 ) ) { 34 | cout<< "Reached destinaiton" << endl; 35 | return true; 36 | } 37 | if( findPath( rowNo, colNo + 1 ) || // move right 38 | findPath( rowNo + 1, colNo ) ) { 39 | return true; 40 | } 41 | return false; 42 | } 43 | 44 | 45 | /* O( numRow*numCol ) time*/ 46 | bool findPathV2( int rowNum, int colNum, vector< pair > &path, 47 | set< pair > &failedPoints ) { 48 | if( rowNum >= numRow || colNum >= numCol || !arr[ rowNum ][ colNum ] ) { 49 | return false; 50 | } 51 | pair p = make_pair( rowNum, colNum ); 52 | if( failedPoints.find( p ) != failedPoints.end() ) { 53 | // ( rowNum, colNum ) leads to no-path 54 | return false; 55 | } 56 | if( rowNum == numRow - 1 && 57 | colNum == numCol - 1 ) { 58 | path.push_back( p ); 59 | return true; 60 | } 61 | if( findPathV2( rowNum + 1, colNum, path, failedPoints ) || 62 | findPathV2( rowNum, colNum + 1, path, failedPoints ) ) { 63 | path.push_back( p ); 64 | return true; 65 | } 66 | failedPoints.insert( p ); 67 | return false; 68 | } 69 | 70 | int main() { 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /17-Hard/8-Circus-Tower.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Circus Tower: 3 | A circus is designing a tower routine consisting of people standing atop one another's 4 | shoulders. For practical and aesthetic reasons, each person must be both shorter and lighter than 5 | the person below him or her. Given the heights and weights of each person in the circus, write a 6 | method to compute the largest possible number of people in such a tower. 7 | 8 | Solution: 9 | The problem is really the following: 10 | We have a list of pairs of items. Find the longest sequence such that both the first and second 11 | items are in non-decreasing order. 12 | 13 | 1. Sort the heights in decreasinn order. 14 | 2. Now in the sorted array find the longest decreasing weight sub-array. 15 | */ 16 | 17 | // g++ 8-Circus-Tower.cpp --std=c++11 18 | 19 | #include 20 | #include 21 | 22 | using std::cout; 23 | using std::endl; 24 | using std::vector; 25 | 26 | bool compHeight( const std::pair a, const std::pair b ) { 27 | return a.first > b.first; 28 | } 29 | 30 | int longestIncreasingWeight( vector< std::pair > htWtPairs ) { 31 | int globalLongest = 1; 32 | int longest = 1; 33 | for( int i = 1; i < htWtPairs.size(); i++ ) { 34 | if( htWtPairs[i].second < htWtPairs[i-1].second ) { 35 | longest += 1; 36 | if( longest > globalLongest ) { 37 | globalLongest = longest; 38 | } 39 | } else { 40 | longest = 1; 41 | } 42 | } 43 | return globalLongest; 44 | } 45 | 46 | int getLongestHtAndWt( vector< std::pair > htWtPairs ) { 47 | std::sort( htWtPairs.begin(), htWtPairs.end(), compHeight ); 48 | return longestIncreasingWeight( htWtPairs ); 49 | } 50 | 51 | int main() { 52 | vector< std::pair > heightAndWeight = { {65, 100}, {70, 150}, {56, 90}, {75, 190}, 53 | {60,85}, {68,110} }; 54 | cout<< getLongestHtAndWt( heightAndWeight ) << endl; 55 | vector< std::pair > heightAndWeight1 = {{1,1}, {3,3}, {7,2}, {6,4}, {9,9}, {8,5}}; 56 | cout<< getLongestHtAndWt( heightAndWeight1 ) << endl; 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /4-Trees-and-Graphs/ValidateBST.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Implement a function to check if a binary tree is a binary search tree. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | class Node { 11 | public: 12 | int key; 13 | Node *left; 14 | Node *right; 15 | }; 16 | 17 | /* Solution #1: In-Order Traversal 18 | Copy the elements to an array, and then check to see if the array is sorted. 19 | This solution takes up a bit of extra memory, but it works if elements are unique. 20 | */ 21 | 22 | int pos = 0; 23 | void copyBstToArray( Node *node, int arr[] ) { 24 | if( node == NULL ) 25 | return; 26 | 27 | copyBstToArray( node->left, arr ); 28 | arr[ pos ] = node->key; 29 | pos++; 30 | copyBstToArray( node->right, arr ); 31 | return; 32 | } 33 | 34 | bool isValidBstV1( Node *node, int size ) { 35 | int *arr = new int[ size ]; 36 | copyBstToArray( node, arr ); 37 | for( int i=0; i < size - 1; i++ ) { 38 | if( arr[i] > arr[ i + 1 ] ) 39 | return false; 40 | } 41 | return true; 42 | } 43 | 44 | /* 45 | Solution 2: Without using array 46 | */ 47 | 48 | int val = INT_MIN; 49 | bool isValidBstV2( Node *node ) { 50 | if( node == NULL ) 51 | return true; 52 | if( !isValidBstV2( node->left ) ) 53 | return false; 54 | if( val != INT_MIN && node->key < val ) { 55 | return false; 56 | } 57 | if( !isValidBstV2( node->right ) ) 58 | return false; 59 | return true; // All good 60 | } 61 | 62 | /* 63 | Solution 3: Using property "left <= current < right" 64 | all left nodes must be less than or equal to the current node, 65 | which must be less than all the right nodes. 66 | */ 67 | bool isValidBstV3( Node *node, int min, int max ) { 68 | if( node == NULL ) 69 | return true; 70 | 71 | if( node->key < min || node->key > max ) { 72 | return false; 73 | } 74 | if( !isValidBstV3( node->left, min, node->key ) ) { 75 | return false; 76 | } 77 | 78 | if( !isValidBstV3( node->right, node->key, max ) ) { 79 | return false; 80 | } 81 | return true; 82 | } 83 | 84 | int main() { 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /1-Array-And-String/OneAway.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | There are three types of edits that can be performed on strings: insert a character, 3 | remove a character, or replace a character. Given two strings, write a function to 4 | check if they are one edit (or zero edits) away. 5 | EXAMPLE 6 | pale, ple -> true 7 | pales, pale -> true 8 | pale, bale -> true 9 | pale, bake -> false 10 | */ 11 | 12 | #include 13 | 14 | using namespace std; 15 | 16 | bool checkReplacement( string s1, string s2 ) { 17 | bool diffFound = false; 18 | for( int i = 0; i < s1.length(); i++ ) { 19 | if( s1[ i ] != s2[ i ] ) { 20 | if( diffFound ) { 21 | return false; 22 | } 23 | diffFound = true; 24 | } 25 | } 26 | return true; 27 | } 28 | 29 | bool checkRemove( string &s1, string &s2 ) { 30 | bool diffFound = false; 31 | int j = 0; // index in string s2 32 | for( int i = 0; i < s1.length(); i++, j++ ) { 33 | if( s1[ i ] != s2[ j ] ) { 34 | i++; 35 | if( diffFound ) 36 | return false; 37 | diffFound = true; 38 | } 39 | } 40 | return true; 41 | } 42 | 43 | bool isStringOneEditAway( string &s1, string &s2 ) { 44 | // If string s1 and s2 are of equal length then check for replaceement 45 | // else check for remove( removing 1 char from larger string should 46 | // give smaller string ). 47 | // Insert is opposite of remove. 48 | 49 | if( s1.length() == s2.length() ) { 50 | return checkReplacement( s1, s2 ); 51 | } else { 52 | if( s1.length() - 1 == s2.length() ) 53 | return checkRemove( s1, s2 ); 54 | if( s2.length() - 1 == s1.length() ) 55 | return checkRemove( s2, s1 ); 56 | } 57 | return false; 58 | } 59 | 60 | int main() { 61 | string a1 = "pale"; 62 | string a2 = "ple"; 63 | cout<< isStringOneEditAway( a1, a2 ) << endl; 64 | 65 | string b1 = "pales"; 66 | string b2 = "pale"; 67 | cout<< isStringOneEditAway( b1, b2 ) << endl; 68 | 69 | string c1 = "pale"; 70 | string c2 = "bale"; 71 | cout<< isStringOneEditAway( c1, c2 ) << endl; 72 | 73 | string d1 = "pale"; 74 | string d2 = "bake"; 75 | cout<< isStringOneEditAway( d1, d2 ) << endl; 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/6-Blue-Eyed-Island.txt: -------------------------------------------------------------------------------- 1 | Blue-Eyed Island: 2 | A bunch of people are living on an island, when a visitor comes with a strange 3 | order: all blue-eyed people must leave the island as soon as possible. There will 4 | be a flight out at 8:00pm every evening. Each person can see everyone else's eye color, 5 | but they do not know their own (nor is anyone allowed to tell them). Additionally, 6 | they do not know how many people have blue eyes, although they do know that at least 7 | one person does. How many days will it take the blue-eyed people to leave? 8 | 9 | Solution: 10 | Let's apply the Base Case and Build approach. Assume that there are n people on the 11 | island and c of them have blue eyes. We are explicitly told that c > 0. 12 | 13 | Case c = 1: Exactly one person has blue eyes. 14 | Assuming all the people are intelligent, the blue-eyed person should look around and 15 | realize that no one else has blue eyes. Since he knows that at least one person has 16 | blue eyes, he must conclude that it is he who has blue eyes. Therefore, he would take 17 | the flight that evening. 18 | 19 | Case c = 2: Exactly two people have blue eyes. 20 | The two blue-eyed people see each other, but are unsure whether c is 1, or 2. They know, 21 | from the previous case, that if c = 1 the blue-eyed person would leave on the first night. 22 | Therefore, if the other blue-eyed person is still there, he must deduce that c = 2, which 23 | means that he himself has blue eyes. Both men would then leave on the second night. 24 | 25 | Case c > 2: The General Case. 26 | As we increase c, we can see that this logic continues to apply. If c = 3, then those three 27 | people will immediately know that there are either 2 or 3 people with blue eyes. If there were 28 | two people, then those two people would have left on the second night. So, when the others are 29 | still around after that night, each person would conclude that c = 3 and that they, therefore, 30 | have blue eyes too. They would leave that night. 31 | 32 | This same pattern extends up through any value of c. Therefore, if c men have blue eyes, it will 33 | take c nights for the blue-eyed men to leave. All will leave on the same night. 34 | -------------------------------------------------------------------------------- /16-Moderate/10-No-Of-Living-People.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Living People: 3 | Given a list of people with their birth and death years, implement a method to compute the 4 | year with the most number of people alive. You may assume that all people were born between 5 | 1900 and 2000 (inclusive). If a person was alive during any portion of that year, they should 6 | be included in that year's count. For example, Person (birth = 1908, death = 1909) is included 7 | in the counts for both 1908 and 1909. 8 | */ 9 | 10 | // g++ 10-No-Of-Living-People.cpp --std=c++14 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | using std::cout; 17 | using std::endl; 18 | using std::vector; 19 | using std::set; 20 | 21 | struct Person { 22 | int yearOfBirth; 23 | int yearOfDeath; 24 | 25 | Person( int yearBirth, int yearDeath ) { 26 | yearOfBirth = yearBirth; 27 | yearOfDeath = yearDeath; 28 | } 29 | }; 30 | 31 | struct Year { 32 | int year; 33 | bool birth; 34 | 35 | Year( int year_, bool birth_ ) { 36 | year = year_; 37 | birth = birth_; 38 | } 39 | 40 | bool operator< ( const Year &y ) const { 41 | return year < y.year; 42 | } 43 | }; 44 | 45 | int main() { 46 | vector persons = { Person( 12, 15 ), Person( 20, 90 ), Person( 10, 98 ), 47 | Person( 01, 72 ), Person( 10, 98 ), Person( 23, 82 ), 48 | Person( 13, 98 ), Person( 90, 98 ), Person( 83, 99 ), 49 | Person( 75, 94 ) }; 50 | 51 | vector< Year > years; 52 | for( auto person : persons ) { 53 | years.push_back( Year( person.yearOfBirth, true ) ); 54 | // added 1 since death year is also included. 55 | years.push_back( Year( person.yearOfDeath + 1, false ) ); 56 | } 57 | 58 | std::sort( years.begin(), years.end() ); 59 | 60 | int maxPeople = 0; 61 | int maxYear = 0; 62 | int tmp = 0; 63 | for( auto y : years ) { 64 | if( y.birth ) { 65 | tmp += 1; 66 | if( tmp > maxPeople ) { 67 | maxPeople = tmp; 68 | maxYear = y.year; 69 | } 70 | } else { 71 | tmp -= 1; 72 | } 73 | } 74 | 75 | cout<< "Max people alive " << maxPeople << " in year " << maxYear << endl; 76 | return 0; 77 | } 78 | 79 | -------------------------------------------------------------------------------- /8-Recursion-And-Dynamic-Programming/EightQueen.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Eight Queens: 3 | Write an algorithm to print all ways of arranging eight queens on an 8x8 4 | chess board so that none of them share the same row, column, or diagonal. 5 | In this case, "diagonal" means all diagonals, not just the two that bisect 6 | the board. 7 | 8 | Note: Eight queens puzzle has 92 distinct solutions. 9 | */ 10 | 11 | #include 12 | #include 13 | #include // abs 14 | 15 | using std::cout; 16 | using std::endl; 17 | using std::vector; 18 | 19 | bool checkValid( int rowNum, int colNum, vector< int > &columns ) { 20 | /* 21 | Check if ( rowNum, colNum ) is a valid spot for a queen by checking if 22 | there is a queen in the same col or diagonal. We don't need to check 23 | it for queens in the same row because the calling placeQueen only attempts 24 | to place one queen at a time. We know this row is empty. 25 | */ 26 | for( int row=0; row &columns ) { 40 | if( rowNum == gridSize ) { 41 | cout<< "Valid queen placements" << endl; 42 | for( int i = 0; i < gridSize; i++ ) { 43 | cout<< columns[ i ] << endl; 44 | } 45 | return; 46 | } 47 | for( int col = 0; col < gridSize; col++ ) { 48 | if( checkValid( rowNum, col, columns ) ) { 49 | columns[rowNum] = col; 50 | placeQueen( rowNum + 1, gridSize, columns ); 51 | } 52 | } 53 | } 54 | 55 | int main() { 56 | static int gridSize = 8; 57 | // We don't need nxn array to store the position of queens. Instead we can store 58 | // the columns no for each row. 59 | vector< int > columns; 60 | for( int i = 0; i < gridSize; i++ ) { 61 | columns.push_back( 0 ); 62 | } 63 | placeQueen( 0, gridSize, columns ); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /16-Moderate/14-Best-Line.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Best Line: Given a two-dimensional graph with points on it, find a line which 3 | passes the most number of points. 4 | 5 | Solution: O( N^2) where N is number of points. 6 | Draw an infinite line (that is, not a line segment) between every two points and, 7 | using a hash table, track which line is the most common. 8 | 9 | We will represent a line as a slope and y-intercept (as opposed to a pair of points), 10 | which allows us to easily check to see if the line from (x1, y1) to (x2, y2) is equivalent 11 | to the line from (x3, y3) to (x4, y4). 12 | 13 | To find the most common line then, we just iterate through all lines segments, using a hash 14 | table to count the number of times we've seen each line. 15 | 16 | Input: [[1,1],[2,2],[3,3]] 17 | Output: 3 18 | 19 | Input: [[1,1],[3,2],[5,3],[4,1],[2,3],[1,4]] 20 | Output: 4 */ 21 | 22 | // g++ 14-Best-Line.cpp --std=c++14 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | using std::vector; 29 | using std::unordered_map; 30 | 31 | class Point { 32 | public: 33 | int x; 34 | int y; 35 | 36 | Point( int x, int y ) : x(x), y(y) {} 37 | }; 38 | 39 | double getHash( double slope, double intercept ) { 40 | double hash; 41 | hash = slope + intercept; // TODO: use better hash function 42 | return hash; 43 | } 44 | 45 | // hash => count 46 | unordered_map lines; 47 | 48 | void getLine( Point A, Point B ) { 49 | double slope = (B.y - A.y)/( B.x-B.y); 50 | double intercept = B.y - slope*B.x; 51 | // create line and populate hash table in the line is not there already. 52 | } 53 | 54 | void getBestLine( vector< Point> points ) { 55 | for( int i=0; i < points.size() - 1; ++i ) { 56 | for( int j=i+1; j < points.size(); ++j ) { 57 | getLine( points[i], points[j] ); 58 | } 59 | } 60 | // iterate through hash map and return the line with max count 61 | } 62 | 63 | int main() { 64 | vector< Point > points1 = { Point(1,1), Point(2,2), Point(3,3) }; 65 | vector< Point > points2 = { Point(1,1), Point(3,2), Point(5,3), Point(4,1), 66 | Point(2,3), Point(1,4) }; 67 | getBestLine( points1 ); 68 | getBestLine( points2 ); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /16-Moderate/25-LRU-Cache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | LRU Cache: 3 | Design and build a "least recently used" cache, which evicts the least recently used item. 4 | The cache should map from keys to values (allowing you to insert and retrieve a value associated 5 | with a particular key) and be initialized with a max size. When it is full, it should evict the least 6 | recently used item. You can assume the keys are integers and the values are strings. 7 | 8 | Solution: 9 | The (key, value) mapping suggests a hash table. This would make it easy to look up the value associated 10 | with a particular key. Unfortunately, a hash table usually would not offer a quick way to remove the most 11 | recently used item. We could mark each item with a timestamp and iterate through the hash table to remove 12 | the item with the lowest timestamp, but that can get quite slow (O(N) for insertions). 13 | 14 | Instead, we could use a linked list, ordered by the most recently used. This would make it easy to mark an 15 | item as the most recently used (just put it in the front of the list) or to remove the least recently used item 16 | (remove the end). Unfortunately, this does not offer a quick way to look up an item by its key. We could 17 | iterate through the linked list and find the item by key. But this could get very slow ( O(N) for retrieval). 18 | 19 | The linked list looks as it did in the earlier example, but now it's a doubly linked list. This allows us to easily 20 | remove an element from the middle of the linked list. The hash table now maps to each linked list node 21 | rather than the value. 22 | 23 | The algorithms now operate as follows: 24 | Inserting Key, Value Pair: Create a linked list node with key, value. Insert into head of linked list. Insert 25 | key -> node mapping into hash table. 26 | 27 | Retrieving Value by Key: Look up node in hash table and return value. Update most recently used item. 28 | 29 | Finding Least Recently Used: Least recently used item will be found at the end of the linked list. 30 | 31 | Updating Most Recently Used: Move node to front of linked list. Hash table does not need to be 32 | updated. 33 | 34 | Eviction: Remove tail of linked list. Get key from linked list node and remove key from hash table. 35 | */ 36 | -------------------------------------------------------------------------------- /16-Moderate/6-Smallest-Difference.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Smallest Difference: 3 | Given two arrays of integers, compute the pair of values (one value in each 4 | array) with the smallest (non-negative) difference. Return the difference. 5 | EXAMPLE 6 | Input { 1, 3, 15, 11,2 }, {23, 127, 235, 19, 8} 7 | Output 3. That is, the pair (11, 8). 8 | 9 | A optimal approach is to sort the arrays. Once the arrays are sorted, we can 10 | find the minimum difference by iterating through the array. 11 | 12 | Consider the following two arrays: 13 | A: { 1, 2, 11, 15 } 14 | B: { 4, 12, 19, 23, 127, 235 } 15 | 16 | Try the following approach: 17 | 1.Suppose a pointer a points to the beginning of A and a pointer b points to the 18 | beginning of B. The current difference between a and b is 3. Store this as the min. 19 | 2.How can we ( potentially ) make this difference smaller? Well, the value at b is bigger 20 | than the value at a, so moving b will only make the difference larger. Therefore, 21 | we want to move a. 22 | 3.Now a points to 2 and b (still) points to 4. This difference is 2, so we should update min. 23 | Move a, since it is smaller. 24 | 4.Now a points to 11 and b points to 4. Move b. 25 | 5.Now a points to 11 and b points to 12. Update min to 1. Move b. 26 | 27 | And so on. 28 | */ 29 | 30 | 31 | // Compile using 'g++ 6-Smallest-Difference.cpp --std=c++14' 32 | #include 33 | #include 34 | #include 35 | 36 | using std::cout; 37 | using std::endl; 38 | using std::vector; 39 | 40 | int smallestDiff( vector A, vector B ) { 41 | // sort in ascending order 42 | std::sort( A.begin(), A.end() ); 43 | std::sort( B.begin(), B.end() ); 44 | 45 | int i = 0, j = 0; 46 | int diff = INT_MAX; 47 | int tmpDiff; 48 | while( i < A.size() && j < B.size() ) { 49 | if ( A[i] > B[j] ) { 50 | tmpDiff = A[i] - B[j]; 51 | j = j + 1; 52 | } else { 53 | tmpDiff = B[j] - A[i]; 54 | i = i + 1; 55 | } 56 | if( tmpDiff < diff ) { 57 | diff = tmpDiff; 58 | } 59 | } 60 | return diff; 61 | } 62 | 63 | int main() { 64 | vector A = { 1, 2, 11, 15 }; 65 | vector B = { 4, 12, 19, 23, 127, 235 }; 66 | cout<< smallestDiff( A, B ) << endl; 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /16-Moderate/18-Pattern-Matching.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Pattern Matching: 3 | You are given two strings, pattern and value. The pattern string consists of just the letters 4 | a and b, describing a pattern within a string. For example, the string catcatgocatgo matches 5 | the pattern aabab (where cat is a and go is b). It also matches patterns like a, ab, and b. 6 | Write a method to determine if value matches pattern. 7 | 8 | Solution: 9 | Brute Force 10 | Iterating through all substrings for a and all possible substrings for b. There are O(n^2) 11 | substrings in a string of length n, so this will actually take O(n^4) time. But then, for 12 | each value of a and b, we need to build the new string of this length and compare it for equality. 13 | This building/comparison step takes O(n) time, giving an overall runtime of 0 (n^5). 14 | 15 | for each possible substring a 16 | for each possible substring b 17 | candidate = buildFromPattern(pattern, a, b) 18 | if candidate equals value 19 | return true 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | using std::cout; 26 | using std::endl; 27 | using std::string; 28 | 29 | string buildPattern( string a, string b, string pattern ) { 30 | string result = ""; 31 | for( int i=0; i < pattern.length(); ++i ) { 32 | if( pattern[i] == 'a' ) { 33 | result = result + a; 34 | } else { 35 | result = result + b; 36 | } 37 | } 38 | return result; 39 | } 40 | 41 | bool isPatternInValue( string pattern, string value ) { 42 | // look for pattern in value 43 | return true; 44 | } 45 | 46 | bool patternMatchingV1( string pattern, string value ) { 47 | if( pattern.length() == 0 ) { 48 | return value.length() == 0; 49 | } 50 | 51 | // get all sub-string 52 | for( int i=0; i < value.length(); ++i ) { 53 | for( int j=1; j + i <= value.length(); ++j ) { 54 | string s = value.substr( i, j ); 55 | cout<< s << endl; 56 | } 57 | } 58 | // for all sub-string build pattern 59 | string res = buildPattern( "cat", "go", pattern ); 60 | cout<< res << endl; 61 | return isPatternInValue( res, value ); 62 | } 63 | 64 | int main() { 65 | string pattern = "aabab"; 66 | string value = "catcatgocatgo"; 67 | 68 | patternMatchingV1( pattern, value ); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /17-Hard/16-The-Masseuse.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | The Masseuse: 3 | A popular masseuse receives a sequence of back-to-back appointment requests and is debating 4 | which ones to accept. She needs a 15-minute break between appointments and therefore she cannot 5 | accept any adjacent requests. Given a sequence of back-to-back appointment requests (all multiples 6 | of 15 minutes, none overlap, and none can be moved), find the optimal (highest total booked minutes) 7 | set the masseuse can honor. Return the number of minutes. 8 | 9 | EXAMPLE 10 | Input: {30, 15, 60, 75, 45, 15, 15, 45} 11 | Output: 180 minutes ({30, 60, 45, 45}) 12 | 13 | INPUT: {75, 105, 120, 75, 90, 135} 14 | OUTPUT: 330 minutes ({75, 120, 135}) 15 | */ 16 | 17 | // g++ 16-The-Masseuse.cpp --std=c++11 18 | 19 | #include 20 | #include 21 | 22 | using std::cout; 23 | using std::endl; 24 | using std::vector; 25 | 26 | int optimalBooking( const vector input ) { 27 | int maxBooking=0; 28 | vector< int > max( input.size(), 0 ); 29 | max[0] = input[0]; 30 | max[1] = input[0] > input[1] ? input[0] : input[1]; 31 | for( int i = 2; i < input.size(); i++ ) { 32 | if( max[i-2] + input[i] > max[ i-1 ] ) { 33 | max[ i ] = max[i-2] + input[i]; 34 | } else { 35 | max[i] = max[i-1]; 36 | } 37 | if( max[i] > maxBooking ) { 38 | maxBooking = max[i]; 39 | } 40 | } 41 | return maxBooking; 42 | } 43 | 44 | int optimalBookingV2( const vector input ) { 45 | int maxBooking=0; 46 | int max; 47 | int maxTwoAway = input[0]; 48 | int maxOneAway = input[0] > input[1] ? input[0] : input[1]; 49 | for( int i = 2; i < input.size(); i++ ) { 50 | if( maxTwoAway + input[i] > maxOneAway ) { 51 | max = maxTwoAway + input[i]; 52 | } else { 53 | max = maxOneAway; 54 | } 55 | maxTwoAway = maxOneAway; 56 | maxOneAway = max; 57 | 58 | if( max > maxBooking ) { 59 | maxBooking = max; 60 | } 61 | } 62 | return maxBooking; 63 | } 64 | 65 | int main() { 66 | vector input1 = {30, 15, 60, 75, 45, 15, 15, 45}; 67 | vector input2 = {75, 105, 120, 75, 90, 135}; 68 | cout<< optimalBooking( input1 ) << endl; 69 | cout<< optimalBooking( input2 ) << endl; 70 | cout<< optimalBookingV2( input1 ) << endl; 71 | cout<< optimalBookingV2( input2 ) << endl; 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /16-Moderate/15-Master-Mind.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Master Mind: 3 | The Game of Master Mind is played as follows: 4 | The computer has four slots, and each slot will contain a ball that is red (R), yellow (Y), green (G) or 5 | blue (B). For example, the computer might have RGGB (Slot #1 is red, Slots #2 and #3 are green, Slot 6 | #4 is blue). 7 | 8 | You, the user, are trying to guess the solution. You might, for example, guess YRGB. 9 | When you guess the correct color for the correct slot, you get a "hit:' If you guess a color that exists 10 | but is in the wrong slot, you get a "pseudo-hit:' Note that a slot that is a hit can never count as a 11 | pseudo-hit. 12 | 13 | For example, if the actual solution is RGBY and you guess GGRR, you have one hit and one pseudohit. 14 | Write a method that, given a guess and a solution, returns the number of hits and pseudo-hits. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | using std::cout; 22 | using std::endl; 23 | using std::string; 24 | using std::unordered_map; 25 | 26 | void score( string actual, string guess ) { 27 | /* 28 | We implement this code by first creating a frequency map which stores 29 | how many times each character occurs in solution, excluding times when 30 | the slot is a "hit". Then, we iterate through guess to count the number 31 | of pseudo-hits. 32 | */ 33 | 34 | int hit=0; 35 | int pseudoHit=0; 36 | 37 | unordered_map count; 38 | count.insert( std::make_pair( 'R', 0 ) ); 39 | count.insert( std::make_pair( 'G', 0 ) ); 40 | count.insert( std::make_pair( 'B', 0 ) ); 41 | count.insert( std::make_pair( 'Y', 0 ) ); 42 | 43 | for( int i = 0; i < actual.length(); ++i ) { 44 | if( actual[ i ] == guess[ i ] ) { 45 | ++hit; 46 | } else { 47 | count[ actual[ i ] ] = count[ actual[ i ] ] + 1; 48 | } 49 | } 50 | 51 | for( int i = 0; i < guess.length(); ++i ) { 52 | if( count[ guess[i] ] > 0 ) { 53 | count[ guess[i] ] = count[ actual[ i ] ] - 1; 54 | pseudoHit++; 55 | } 56 | } 57 | 58 | cout<< "Hit:" << hit << " Pseudo Hit:"<< pseudoHit < 1 <-> 2 <-> 3 <-> 4 <-> 5 <-> 6 22 | */ 23 | 24 | #include 25 | 26 | using std::cout; 27 | using std::endl; 28 | 29 | struct Node { 30 | int key; 31 | Node *left; 32 | Node *right; 33 | Node *next; 34 | Node *prev; 35 | 36 | Node( int key_ ) { 37 | key = key_; 38 | left = NULL; 39 | right = NULL; 40 | 41 | next = NULL; 42 | prev = NULL; 43 | } 44 | }; 45 | 46 | void bstToDll( Node *node, Node *head, Node *tail ) { 47 | if( node->left ) { 48 | bstToDll( node->left, head, node ); 49 | } 50 | if( node->right ) { 51 | bstToDll( node->right, node, tail ); 52 | } 53 | if( node->left == NULL ) { 54 | head->next = node; 55 | node->prev = head; 56 | } 57 | if( node->right == NULL ) { 58 | node->next = tail; 59 | tail->prev = node; 60 | } 61 | } 62 | 63 | void traverseDoublyLinkedList( Node *head, Node *tail ) { 64 | Node *node = head->next; 65 | while( node->next != NULL ) { 66 | cout<< node->key << "->"; 67 | node = node->next; 68 | } 69 | cout<< endl; 70 | } 71 | 72 | int main() { 73 | Node *root = new Node(4); 74 | root->left = new Node(2); 75 | root->right = new Node(5); 76 | root->right->right = new Node(6); 77 | 78 | root->left->left = new Node(1); 79 | root->left->right = new Node(3); 80 | root->left->left->left = new Node(0); 81 | 82 | Node *head = new Node(-1); 83 | Node *tail = new Node(-1); 84 | bstToDll( root, head, tail ); 85 | traverseDoublyLinkedList( head, tail ); 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /17-Hard/18-Shortest-Supersequence.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Shortest Supersequence: 3 | 4 | You are given two arrays, one shorter (with all distinct elements) and one 5 | longer. Find the shortest subarray in the longer array that contains all the elements in the shorter 6 | array. The items can appear in any order. 7 | EXAMPLE 8 | Input: smallArray = { 1, 5, 9 } 9 | largeArray = { 7, 5, 9, 0, 2, 1, 3, '5, 7, 9, 1', 1, 5, 8, 8, 9, 7 } 10 | Output: [ 7, 10 ] 11 | 12 | 13 | Solution: 14 | Iterate through the largeArray backwards for each element 'e' of smallArray. 15 | While doing so compute and store the nextOccurance of 'e' for each element of largeArray. 16 | The maximum of all these nextOccurance at index i will give the closure at index i. 17 | 18 | Compute the minimum diff between index and maximum value of nextOccurance to get min sub-array 19 | which contain all elements of smallArray. 20 | */ 21 | 22 | // g++ 18-Shortest-Supersequence.cpp --std=c++11 23 | 24 | #include 25 | #include 26 | 27 | using std::cout; 28 | using std::endl; 29 | using std::vector; 30 | 31 | void getShortestSupersequence( vector smallArray, vector largeArray ) { 32 | size_t size = largeArray.size(); 33 | vector nextOccurence( size,0 ); 34 | for( auto k : smallArray ) { 35 | int index = -1; 36 | for( int i = size - 1; i >= 0; --i ) { 37 | if( largeArray[i] == k ) { 38 | index = i; 39 | } 40 | if( index == -1 || nextOccurence[ i ] == -1 ) { 41 | nextOccurence[ i ] = -1; 42 | } else if( index > nextOccurence[ i ] ) { 43 | // we are only interested in knowing the max next occurance among all k's 44 | nextOccurence[ i ] = index; 45 | } 46 | } 47 | } 48 | int min = size; 49 | int left = 0; 50 | int right = size - 1; 51 | for( int i = 0; i < size; ++i ) { 52 | if( nextOccurence[ i ] == -1 ) { 53 | continue; 54 | } else if( nextOccurence[ i ] - i < min ) { 55 | min = nextOccurence[ i ] - i; 56 | left = i; 57 | right = nextOccurence[ i ]; 58 | } 59 | } 60 | cout<< "Left index:" << left << " right index:" << right << endl; 61 | } 62 | 63 | int main() { 64 | vector smallerArray = { 1, 5, 9}; 65 | vector largeArray = { 7, 5, 9, 0, 2, 1, 3, 5, 7, 9, 1, 1, 5, 8, 8, 9, 7 }; 66 | getShortestSupersequence( smallerArray, largeArray ); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /2-Linked-Lists/PartitionAroundNode.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Write code to partition a linked list around a value x, such that all 3 | nodes less than x come before all nodes greater than or equal to x. 4 | If x is contained within the list, the values of x only need to be after 5 | the elements less than x (see below). The partition element x can appear 6 | anywhere in the "right partition"; it does not need to appear between the 7 | left and right partitions. 8 | 9 | EXAMPLE 10 | Input: 3->5->8->5->113->2->1 [ partition = 5 ] 11 | Output: 3->1->2->113->5->5->8 12 | */ 13 | 14 | #include 15 | 16 | using namespace std; 17 | 18 | class Node { 19 | private: 20 | int data_; 21 | Node *next_; 22 | public: 23 | Node( int _data ) : data_( _data ), next_( NULL ) {} 24 | ~Node() { next_ = NULL; } 25 | Node * next() { return this->next_; } 26 | int data() { return data_; } 27 | void dataIs( int _data ) { data_ = _data; } 28 | void nextIs( Node *node ) { this->next_ = node; } 29 | }; 30 | 31 | void addFront( Node *head, int data ) { 32 | Node *newNode = new Node( data ); 33 | newNode->nextIs( head->next() ); 34 | head->nextIs( newNode ); 35 | } 36 | 37 | void printLL( Node *node ) { 38 | while( node != NULL ) { 39 | cout<< node->data() << "->"; 40 | node = node->next(); 41 | } 42 | cout << endl; 43 | } 44 | 45 | Node* partition( Node *node, int partition ) { 46 | Node *head = node; 47 | Node *curr = node; 48 | Node *prev = NULL; 49 | while( curr != NULL ) { 50 | if( curr->data() <= partition && 51 | prev != NULL ) { 52 | // move to front 53 | prev->nextIs( curr->next() ); 54 | curr->nextIs( head ); 55 | head=curr; 56 | 57 | curr=prev; // other wise we keep iterating over it again and again 58 | } 59 | prev = curr; 60 | curr = curr->next(); 61 | } 62 | return head; 63 | } 64 | 65 | int main() { 66 | // keep head as a dummy Node 67 | Node *head = new Node( -1 ); 68 | 69 | // create a LL 70 | addFront( head, 8 ); 71 | addFront( head, 12 ); 72 | addFront( head, 14 ); 73 | addFront( head, 16 ); 74 | addFront( head, 10 ); 75 | addFront( head, 14 ); 76 | addFront( head, 18 ); 77 | addFront( head, 10 ); 78 | 79 | // print Linked List 80 | printLL( head->next() ); 81 | 82 | head = partition( head->next(), 12 ); 83 | 84 | printLL( head ); 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /2-Linked-Lists/IntersectionOfLL.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Given two (singly) linked lists, determine if the two lists intersect. Return the 3 | intersecting node. Note that the intersection is defined based on reference, not value. 4 | That is, if the kth node of the first linked list is the exact same node (by reference) 5 | as the jth node of the second linked list, then they are intersecting. 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | class Node { 14 | private: 15 | int data_; 16 | Node *next_; 17 | public: 18 | Node( int _data ) : data_( _data ), next_( NULL ) {} 19 | ~Node() { next_ = NULL; } 20 | Node * next() { return this->next_; } 21 | int data() { return data_; } 22 | void dataIs( int _data ) { data_ = _data; } 23 | void nextIs( Node *node ) { this->next_ = node; } 24 | }; 25 | 26 | void addFront( Node **head, int data ) { 27 | Node *newNode = new Node( data ); 28 | newNode->nextIs( *head ); 29 | *head = newNode; 30 | } 31 | 32 | void printLL( Node *node ) { 33 | while( node != NULL ) { 34 | cout<< node->data() << "->"; 35 | node = node->next(); 36 | } 37 | cout << endl; 38 | } 39 | 40 | Node * findIntersection( Node *l1, Node *l2 ) { 41 | set< Node * > nodeSet; 42 | while( l1 != NULL ) { 43 | nodeSet.insert( l1 ); 44 | l1 = l1->next(); 45 | } 46 | 47 | while( l2 != NULL ) { 48 | if( nodeSet.count( l2 ) == 1 ) 49 | return l2; 50 | l2 = l2->next(); 51 | } 52 | return NULL; 53 | // other approach is to traverse each list, if last node is same then they intersect. 54 | // find the length and then compare node. 55 | } 56 | 57 | int main() { 58 | // create a LL 59 | Node *head1 = NULL; 60 | addFront( &head1, 8 ); 61 | addFront( &head1, 2 ); 62 | addFront( &head1, 4 ); 63 | addFront( &head1, 6 ); 64 | addFront( &head1, 4 ); 65 | 66 | // create another LL 67 | Node *head2 = NULL; 68 | addFront( &head2, 8 ); 69 | addFront( &head2, 2 ); 70 | addFront( &head2, 4 ); 71 | addFront( &head2, 6 ); 72 | addFront( &head2, 2 ); 73 | addFront( &head2, 8 ); 74 | 75 | // print Linked List 76 | printLL( head1 ); 77 | printLL( head2 ); 78 | cout<< "Intersection " << findIntersection( head1, head2 ) << endl; 79 | Node *inter = findIntersection( head1, head1 ); 80 | cout<< "Intersection " << inter << " Data : " << inter->data() < 23 | #include 24 | 25 | using namespace std; 26 | 27 | class SetOfStack { 28 | private: 29 | stack< stack< int > > stackOfStacks; 30 | int threshold_; 31 | public: 32 | SetOfStack( int _threshold ) : threshold_( _threshold ) { 33 | stack< int > s; 34 | stackOfStacks.push(s); 35 | } 36 | 37 | void pop() { 38 | if( not stackOfStacks.top().empty() ) { 39 | stackOfStacks.top().pop(); 40 | } 41 | 42 | if( stackOfStacks.top().empty() && stackOfStacks.size() > 1 ) { 43 | stackOfStacks.pop(); 44 | } 45 | } 46 | 47 | void push( int data ) { 48 | if( stackOfStacks.top().size() == threshold_ ) { 49 | stack< int > newStack; 50 | stackOfStacks.push( newStack ); 51 | } 52 | 53 | if( stackOfStacks.top().size() < threshold_ ) { 54 | stackOfStacks.top().push( data ); 55 | } 56 | } 57 | 58 | int top() { 59 | int data = stackOfStacks.top().top(); 60 | return data; 61 | } 62 | }; 63 | 64 | int main() { 65 | SetOfStack stack( 5 ); 66 | stack.push( 1 ); 67 | stack.push( 2 ); 68 | stack.push( 3 ); 69 | stack.push( 4 ); 70 | stack.push( 5 ); 71 | cout<< " Top " << stack.top() << endl; 72 | stack.push( 6 ); 73 | cout<< " Top " << stack.top() << endl; 74 | stack.pop(); 75 | cout<< " Top " << stack.top() << endl; 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /6-Math-and-Logic-Puzzles/ProbabilityTheory.md: -------------------------------------------------------------------------------- 1 | ## gcd 2 | gcd * lcm = x * y 3 | 4 | ## Checking for Primality 5 | Iterate only up through the square root of n when checking for divisibility. 6 | 7 | ## Generating a List of Primes: The Sieve of Eratosthenes 8 | We start with a list of all the numbers up through some value max. First, we 9 | cross off all numbers divisible by 2. Then, we look for the next prime ( the 10 | next non-crossed off number ) and cross off all numbers divisible by it. By 11 | crossing off all numbers divisible by 2, 3, 5, 7, 11, and so on, we wind up 12 | with a list of prime numbers from 2 through max. 13 | 14 | ## Probability: 15 | Probability of A and B 16 | P( A and B ) = P( B given A ) . P(A) 17 | 18 | **example**: 19 | What's the probability of picking an even number and a number between 1 and 5. 20 | The odds of picking a number between 1 and 5 is 50%, and the odds of a number 21 | between 1 and 5 being even is 40%. So, the odds of doing both are: 22 | 23 | P( x is even and x <= 5 ) = P( x is even given x <= 5 ). P( x <= 5 ) 24 | = ( 2/5 ) * ( 1/2 ) 25 | = 1/5 26 | 27 | Observe that since 'P( A and B ) = P( B given A ) P(A)' the probability of A given B 28 | in terms of the reverse: 29 | P( A given B ) = P( B given A ).P(A) / P(B) 30 | The above equation is called Bayes'Theorem. 31 | 32 | ### Probability of A or B 33 | P( A or B ) = P(A) + P(B) - P( A and B ) 34 | 35 | ### Independence 36 | If A and B are independent ( that is, one happening tells you nothing about the other 37 | happening ), then 38 | P( A and B ) = P(A).P(B) 39 | 40 | This rule simply comes from recognizing that P( B given A ) = P(B), since A indicates 41 | nothing about B. 42 | 43 | ### Mutual Exclusivity 44 | If A and B are mutually exclusive ( that is, if one happens, then the other cannot happen ), then 45 | P( A or B ) = P(A) + P(B) 46 | 47 | This is because P( A and B ) = 0, so this term is removed from the earlier 48 | P(A or B) equation. 49 | 50 | Many people, strangely, mix up the concepts of independence and mutual exclusivity. They are 51 | entirely different. In fact, two events cannot be both independent and mutually exclusive 52 | ( provided both have probabilities greater than 0 ). Why? Because mutual exclusivity means 53 | that if one happens then the other cannot. Independence, however, says that one event happening 54 | means absolutely nothing about the other event. Thus, as long as two events have non-zero probabilities, 55 | they will never be both mutually exclusive and independent. -------------------------------------------------------------------------------- /16-Moderate/8-English-Int.cpp: -------------------------------------------------------------------------------- 1 | /* English Int: 2 | Given any integer, print an English phrase that describes the integer 3 | ( e.g. "One Thousand, Two Hundred Thirty Four"). */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using std::cout; 11 | using std::endl; 12 | using std::vector; 13 | using std::string; 14 | using std::stack; 15 | 16 | class IntToEnglish { 17 | static const vector< string > digitMap; 18 | static const vector< string > tens; 19 | static const vector< string > bigs; 20 | 21 | string intToEngHelper( int num ) { 22 | string out=""; 23 | if( num > 100 ) { 24 | int div = num / 100; 25 | out += digitMap[ div ] + " hundred "; 26 | num = num % 100; 27 | if( num < 20 ) { 28 | out += digitMap[ num ]; 29 | } else { 30 | div = num/10; 31 | out += tens[ div - 2 ]; // since index stars from "twenty" 32 | out += " " + digitMap[ num % 10 ]; 33 | } 34 | } 35 | return out; 36 | } 37 | 38 | public: 39 | string intToEng( int number ) { 40 | if( number == 0 ) { 41 | return digitMap[ number ]; 42 | } 43 | if( number < 0 ) { 44 | return "Negative " + intToEng( -1*number ); 45 | } 46 | int bigsIndex = 0; 47 | stack< string> s; 48 | while( number > 1000 ) { 49 | s.push( bigs[ bigsIndex ] ); 50 | s.push( intToEngHelper( number % 1000 ) ); 51 | number = number / 1000; 52 | bigsIndex += 1; 53 | } 54 | if( number > 0 ) { 55 | s.push( bigs[bigsIndex] ); 56 | s.push( intToEngHelper( number ) ); 57 | } 58 | string output = ""; 59 | while( !s.empty() ) { 60 | output += " " + s.top(); 61 | s.pop(); 62 | } 63 | return output; 64 | } 65 | }; 66 | 67 | const vector IntToEnglish::digitMap = { "zero", "one", "two", "three", "four", 68 | "five", "six", "seven", "eight", "nine", 69 | "ten", "eleven", "twelve", "thirteen", 70 | "fourteen", "fifteen", "sixteen", "seventeen", 71 | "eighteen", "ninteen" }; 72 | const vector IntToEnglish::tens = { "twenty", "thirty", "fourty", "fifty", "sixty", 73 | "seventy", "eighty", "ninty" }; 74 | const vector IntToEnglish::bigs = { "", "thousand", "million", "billlion" }; 75 | 76 | int main() { 77 | IntToEnglish intToEng; 78 | cout << "764542: " << intToEng.intToEng( 764542 ) << endl; 79 | cout << "542: " << intToEng.intToEng( 542 ) << endl; 80 | cout << "134765542: " << intToEng.intToEng( 134765542 ) << endl; 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /12-C-And-C++/SmartPointer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Write a smart pointer class. A smart pointer is a data type, usually 3 | implemented with templates, that simulates a pointer while also 4 | providing automatic garbage collection. It automatically counts the 5 | number of references to a SmartPointer< T* > object and frees the 6 | object of type T when the reference count hits zero. 7 | */ 8 | 9 | /* 10 | Note: 11 | A smart pointer is the same as a normal pointer, but it provides safety 12 | via automatic memory management. It avoids issues like dangling pointers, 13 | memory leaks and allocation failures. The smart pointer must maintain a 14 | single reference count for all references to a given object. 15 | */ 16 | 17 | #include 18 | 19 | using namespace std; 20 | 21 | template< class T > class SmartPointer { 22 | public: 23 | SmartPointer( T *ptr ) { 24 | ref = ptr; 25 | ref_count = ( unsigned * ) malloc( sizeof( unsigned int ) ); 26 | *ref_count = 1; 27 | } 28 | 29 | SmartPointer( SmartPointer &sptr ) { 30 | ref = sptr.ref; 31 | ref_count = sptr.ref_count; 32 | ++( *ref_count ); 33 | } 34 | 35 | /* Override the equal operator, so that when you set one smart 36 | pointer equal to another the old smart pointer has its 37 | reference count decremented and the new smart pointer has its 38 | reference count incrememented. */ 39 | SmartPointer & operator=( SmartPointer & sptr ) { 40 | if( this == &sptr ) 41 | return *this; 42 | 43 | /* If already assigned to an object, remove one reference. */ 44 | if( *ref_count > 0 ) { 45 | remove(); 46 | } 47 | 48 | ref = sptr.ref; 49 | ref_count = sptr.ref_count; 50 | ++( *ref_count ); 51 | return *this; 52 | } 53 | 54 | ~SmartPointer() { 55 | /* We are destroying a reference to the object. Decrement ref_count. 56 | If ref_count is 0, then free the memory created by the integer and 57 | destroy the object */ 58 | remove(); 59 | } 60 | 61 | T getValue() { 62 | return *ref; 63 | } 64 | 65 | protected: 66 | void remove() { 67 | --( *ref_count ); 68 | if( *ref_count == 0 ) { 69 | delete ref; 70 | free( ref_count ); 71 | 72 | ref = NULL; 73 | ref_count = NULL; 74 | } 75 | } 76 | 77 | private: 78 | T *ref; 79 | unsigned *ref_count; 80 | }; 81 | 82 | class Node { 83 | public: 84 | int key; 85 | }; 86 | 87 | int main() { 88 | SmartPointer< Node > nodePtr( new Node() ); 89 | nodePtr.getValue(); 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /16-Moderate/16-Sub-Sort.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Sub Sort: 3 | Given an array of integers, write a method to find indices m and n such that if you sorted 4 | elements m through n, the entire array would be sorted. Minimize n - m (that is, find the 5 | smallest such sequence). 6 | EXAMPLE 7 | Input: 1, 2, 4, 7, 10, 11, 8, 12, 5, 6, 16, 18, 19 8 | Output: (3, 9) 9 | 10 | Solution: 11 | 1. Get the increasing sequence from the left side( index 0 ), seqLeft . 12 | 2. Get the decreasing sequence from right side( index size()-1 ), seqRight. 13 | 3. Get the min element in middle sequence and right. 14 | 4. Get the max element in middle sequence and left. 15 | 5. Position of min in left seq and position of max in right seq would be the result. 16 | */ 17 | 18 | // g++ 16-Sub-Sort.cpp --std=c++14 19 | 20 | #include 21 | #include 22 | 23 | using std::cout; 24 | using std::endl; 25 | using std::vector; 26 | 27 | void subSort( vector v ) { 28 | int leftSeq = 0; 29 | for( int i = 1; i < v.size(); ++i ) { 30 | if( v[i] >= v[ i-1 ] ) { 31 | ++leftSeq; 32 | continue; 33 | } 34 | break; 35 | } 36 | if( leftSeq == v.size() - 1 ) { 37 | cout<< "already increasing sequence" << endl; 38 | return; 39 | } 40 | cout<< "Left seq index:" << leftSeq << endl; 41 | 42 | 43 | int rightSeq = v.size() - 1; 44 | for( int i = v.size() - 2; i >= 0; --i ) { 45 | if( v[i] <= v[ i + 1 ] ) { 46 | --rightSeq; 47 | continue; 48 | } 49 | break; 50 | } 51 | cout<< "Right seq index:" << rightSeq << endl; 52 | 53 | int minNo = v[ leftSeq ]; 54 | for( int i = leftSeq+1; i < rightSeq; i++ ) { 55 | if( v[ i ] < minNo ) { 56 | minNo = v[i]; 57 | } 58 | } 59 | int maxNo = v[ rightSeq ]; 60 | for( int i = rightSeq-1; i > leftSeq; --i ) { 61 | if( maxNo < v[ i ] ) { 62 | maxNo = v[i]; 63 | } 64 | } 65 | cout<< maxNo << " " << minNo << endl; 66 | 67 | // now find the index of minNo in leftSeq and index of maxNo in rightSeq 68 | for( int i = 0; i <= leftSeq; i++ ) { 69 | if( minNo < v[i] ) { 70 | cout<< "Left index: " << i << endl; 71 | break; 72 | } 73 | } 74 | for( int i = rightSeq; i < v.size(); i++ ) { 75 | if( maxNo < v[i] ) { 76 | cout<< "Right index:" << i - 1 << endl; 77 | break; 78 | } 79 | } 80 | } 81 | 82 | int main() { 83 | vector< int > v1 = {1, 2, 3, 3, 4, 6, 7}; 84 | vector v2 = { 1, 2, 4, 7, 10, 11, 8, 6, 12, 5, 6, 16, 18, 19 }; 85 | subSort( v1 ); 86 | subSort( v2 ); 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /17-Hard/17-Multi-Search.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Multi Search: 3 | Given a string b and an array of smaller strings T, design a method to search b for 4 | each small string in T. 5 | 6 | Example: 7 | T = { "is", "ppi", "hi", "sis", "i", "ssippi" } 8 | b = "mississippi" 9 | 10 | Solution 1: 11 | Just search through the bigger string for each instance of the smaller string. 12 | 13 | Solution 2: 14 | We should think about how we can tackle all the elements in T at once, or somehow re-use work. 15 | One way is to create a trie-like data structure using each suffix in the bigger string. 16 | For the string bibs, the suffix list would be: bibs, ibs, bs, s. 17 | */ 18 | 19 | // g++ 17-Multi-Search.cpp --std=c++11 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | using std::cout; 27 | using std::endl; 28 | using std::unordered_map; 29 | using std::list; 30 | using std::string; 31 | 32 | class TrieNode { 33 | public: 34 | unordered_map< char, TrieNode* > children; 35 | list suffixStartPos; // position in original string where suffix starts 36 | }; 37 | 38 | class Trie { 39 | TrieNode *root; 40 | public: 41 | Trie() { 42 | root = new TrieNode(); 43 | } 44 | 45 | void insert( string suffix, int pos ); 46 | list search( string s ); 47 | }; 48 | 49 | void Trie::insert( string suffix, int pos ) { 50 | TrieNode *node = root; 51 | for( auto c : suffix ) { 52 | if( node->children.find( c ) == node->children.end() ) { 53 | node->children.insert( std::make_pair( c, new TrieNode() ) ); 54 | } 55 | node = node->children[ c ]; 56 | // along the path put position where it start in original string 57 | node->suffixStartPos.push_back( pos ); 58 | } 59 | } 60 | 61 | list Trie::search( string s ) { 62 | TrieNode *node = root; 63 | list< int > searchPos; 64 | for( auto c : s ) { 65 | if( node->children.find( c ) != node->children.end() ) { 66 | node = node->children[c]; 67 | } else { 68 | return searchPos; 69 | } 70 | } 71 | return node->suffixStartPos; 72 | } 73 | 74 | int main() { 75 | Trie trie; 76 | string input = "mississippi"; 77 | for( size_t i = 0; i < input.length(); ++i ) { 78 | trie.insert( input.substr( i ), i ); 79 | } 80 | list< int > searchPos; 81 | searchPos = trie.search( "is" ); 82 | cout<< searchPos.size() << endl; 83 | searchPos = trie.search( "ppi" ); 84 | cout<< searchPos.size() << endl; 85 | searchPos = trie.search( "hi" ); 86 | cout<< searchPos.size() << endl; 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /2-Linked-Lists/LoopDetectionInLL.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Given a circular linked list, implement an algorithm that returns the node at the 3 | beginning of the loop. 4 | 5 | DEFINITION 6 | Circular linked list: A (corrupt) linked list in which a node's next pointer points 7 | to an earlier node, so as to make a loop in the linked list. 8 | 9 | EXAMPLE 10 | Input: A -> B -> C -> D -> E - > C [ the same C as earlier ] 11 | Output: C 12 | */ 13 | 14 | /* 15 | 1. Create two pointers, FastPointer and SlowPointer. 16 | 2. Move FastPointer at a rate of 2 steps and SlowPointer at a rate of 1 step. 17 | 3. When they collide, move SlowPointer to LinkedListHead. Keep FastPointer where it is. 18 | 4. Move SlowPointer and FastPointer at a·rate of one step. Return the new collision point. 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | using namespace std; 25 | 26 | class Node { 27 | private: 28 | int data_; 29 | Node *next_; 30 | public: 31 | Node( int _data ) : data_( _data ), next_( NULL ) {} 32 | ~Node() { next_ = NULL; } 33 | Node * next() { return this->next_; } 34 | int data() { return data_; } 35 | void dataIs( int _data ) { data_ = _data; } 36 | void nextIs( Node *node ) { this->next_ = node; } 37 | }; 38 | 39 | Node* addFront( Node **head, int data ) { 40 | Node *newNode = new Node( data ); 41 | newNode->nextIs( *head ); 42 | *head = newNode; 43 | return newNode; 44 | } 45 | 46 | void printLL( Node *node ) { 47 | while( node != NULL ) { 48 | cout<< node->data() << "->"; 49 | node = node->next(); 50 | } 51 | cout << endl; 52 | } 53 | 54 | Node *loop( Node *node ) { 55 | set< Node * > nodeSet; 56 | while( node != NULL ) { 57 | if( nodeSet.count( node ) == 0 ) { 58 | nodeSet.insert( node ); 59 | } else { 60 | return node; 61 | } 62 | node = node->next(); 63 | } 64 | return NULL; 65 | } 66 | 67 | int main() { 68 | Node *head = NULL; 69 | 70 | // create a LL 71 | Node *node = addFront( &head, 8 ); 72 | addFront( &head, 2 ); 73 | addFront( &head, 4 ); 74 | 75 | // print Linked List 76 | printLL( head ); 77 | cout<< "Loop node " << loop( head ) << endl; 78 | 79 | // create loop 80 | addFront( &head, 6 ); 81 | addFront( &head, 4 ); 82 | Node *node1 = addFront( &head, 2 ); 83 | addFront( &head, 8 ); 84 | node->nextIs( node1 ); 85 | 86 | // print Linked List 87 | // printLL( head ); commented because of corrupted link-list 88 | 89 | node = loop( head ); 90 | cout<< "Loop node " << node << " data "<< node->data() < 10 billion * 100 char per URL * 4 byte per character. 10 | 11 | Let's just pretend for a moment that we were miraculously holding this data in memory, since it's useful 12 | to first construct a solution for the simple version. Under this version of the problem, we would just create 13 | a hash table where each URL maps to true if it's already been found elsewhere in the list. As an alternative 14 | solution, we could sort the list and look for the duplicate values that way. That will take a bunch of extra 15 | time and offers few advantages. 16 | 17 | What happens when we have all 4000 gigabytes of data and we can't store it all in memory? We could solve this 18 | either by storing some of the data on disk or by splitting up the data across machines. 19 | 20 | ### Solution 1: Disk Storage 21 | If we stored all the data on one machine, we would do two passes of the document. The first pass would 22 | split the list of URLs into 4000 chunks of 1 GB each. An easy way to do that might be to store each URL in 23 | a file named .txt where x = hash(url)%4000. That is, we divide up the URLs based on their hash 24 | value (modulo the number of chunks). This way, all URLs with the same hash value would be in the same file. 25 | In the second pass, we would essentially implement the simple solution we came up with earlier: load each 26 | file into memory, create a hash table of the URLs, and look for duplicates. 27 | 28 | ### Solution 2: Multiple Machines 29 | The other solution is to perform essentially the same procedure, but to use multiple machines. In this solution, 30 | rather than storing the data in file . txt, we would send the URL to machine x. 31 | Using multiple machines has pros and cons. The main pro is that we can **parallelize the operation**, such 32 | that all 4000 chunks are processed simultaneously. For large amounts of data, this might result in a faster 33 | solution. 34 | The disadvantage though is that we are now relying on 4000 different machines to operate perfectly. That 35 | may not be realistic ( particularly with more data and more machines ), and we'll need to start considering 36 | how to handle failure. Additionally, we have increased the complexity of the system simply by involving so 37 | many machines. -------------------------------------------------------------------------------- /12-C-And-C++/HashTable-Vs-STL-Map.txt: -------------------------------------------------------------------------------- 1 | Hash Table vs STL Map: 2 | 3 | In a hash table a value is stored by calling a hash function on a key. Values are not stored 4 | in sorted order. Additionally, since hash tables use the key to find the index that will store 5 | the value, an insert or lookup can be done in amortized O(1) time ( assuming few collisions in 6 | the hash table ). In a hash table, one must also handle potential collisions. This is often done 7 | by chaining, which means to create a linked list of all the values whose keys map to a particular 8 | index. 9 | 10 | An STL map inserts the key/value pairs into a binary search tree based on the keys. There is no 11 | need to handle collisions, and, since the tree is balanced, the insert and lookup time is guaranteed 12 | to be O(log N). 13 | 14 | How is a hash table implemented? 15 | A hash table is traditionally implemented with an array of linked lists. When we want to insert 16 | a key/value pair, we map the key to an index in the array using a hash function. The value is then 17 | inserted into the linked list at that position. 18 | 19 | Note that the elements in a linked list at a particular index of the array do not have the same key. 20 | Rather, hashFunction(key) is the same for these values. Therefore, in order to retrieve the value for 21 | a specific key, we need to store in each node both the exact key and the value. 22 | 23 | To summarize, the hash table will be implemented with an array of linked lists, where each node in the 24 | linked list holds two pieces of data: the value and the original key. In addition, we will want to note 25 | the following design criteria: 26 | 27 | 1. We want to use a good hash function to ensure that the keys are well distributed. If they are not 28 | well distributed, then we would get a lot of collisions and the speed to find an element would decline. 29 | 30 | 2. No matter how good our hash function is, we will still have collisions, so we need a method for handling 31 | them. This often means chaining via a linked list, but it's not the only way. 32 | 33 | 3. We may also wish to implement methods to dynamically increase or decrease the hash table size depending 34 | on capacity. For example, when the ratio of the number of elements to the table size exceeds a certain 35 | threshold, we may wish to increase the hash table size. This would mean creating a new hash table and 36 | transferring the entries from the old table to the new table. Because this is an expensive operation, we 37 | want to be careful to not do it too often. 38 | 39 | 40 | What can be used instead of a hash table, if the number of inputs is small? 41 | You can use an STL map or a binary tree. Although this takes O( log(n) ) time, the number of inputs may 42 | be small enough to make this time negligible. 43 | -------------------------------------------------------------------------------- /9-System-Design-And-Scalability/2-Social-Networks/shortestPathInGraph.cpp: -------------------------------------------------------------------------------- 1 | /* g++ shortestPathInGraph.cpp --std=c++11 */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::cout; 10 | using std::endl; 11 | using std::list; 12 | using std::vector; 13 | using std::unordered_map; 14 | using std::queue; 15 | 16 | class Graph { 17 | public: 18 | list< int > vertices; 19 | vector< vector< int > > edges; // adjacency list 20 | 21 | Graph( int noOfVertices ) { 22 | edges.resize( noOfVertices ); 23 | } 24 | 25 | vector shortestPath( int source, int dest ) { 26 | unordered_map visited( vertices.size() ); 27 | for( int i = 0; i < vertices.size(); i++ ) { 28 | visited[ i ] = false; 29 | } 30 | 31 | vector path( vertices.size(), -1 ); 32 | queue< int > toVisitQueue; 33 | toVisitQueue.push( source ); 34 | visited[ source ] = true; 35 | 36 | while( !toVisitQueue.empty() ) { 37 | int vertex = toVisitQueue.front(); 38 | toVisitQueue.pop(); 39 | cout<< ":" << vertex << endl; 40 | 41 | for( auto v : edges[ vertex ] ) { 42 | if( !visited[ v ] ) { 43 | path[ v ] = vertex; 44 | toVisitQueue.push( v ); 45 | visited[ v ] = true; 46 | if( v == dest ) { 47 | return path; 48 | } 49 | } 50 | } 51 | } 52 | return path; 53 | } 54 | 55 | }; 56 | 57 | int main() { 58 | /* 59 | Example graph: 60 | 0 61 | / \ 62 | / \ 63 | / \ 64 | 1 2 65 | | 66 | | 67 | | 68 | | 69 | 3------- 4 70 | \ / 71 | \ / 72 | 5 73 | */ 74 | 75 | int noOfVertices = 6; 76 | /* create a graph */ 77 | Graph graph( noOfVertices ); 78 | for( int i = 0; i < noOfVertices; i++ ) { 79 | // add vertices 80 | graph.vertices.push_back( i ); 81 | } 82 | // add edges 83 | graph.edges[ 0 ].push_back(1); 84 | graph.edges[ 0 ].push_back(2); 85 | graph.edges[ 1 ].push_back(0); 86 | graph.edges[ 2 ].push_back(0); 87 | graph.edges[ 2 ].push_back(4); 88 | graph.edges[ 3 ].push_back(4); 89 | graph.edges[ 3 ].push_back(5); 90 | graph.edges[ 4 ].push_back(2); 91 | graph.edges[ 4 ].push_back(3); 92 | graph.edges[ 4 ].push_back(5); 93 | graph.edges[ 5 ].push_back(3); 94 | graph.edges[ 5 ].push_back(5); 95 | 96 | int src = 0; 97 | int dest = 3; 98 | vector path = graph.shortestPath( 0, 3 ); 99 | 100 | // print path 101 | int prev = 3; 102 | while( prev != src ) { 103 | cout<< prev << "<-"; 104 | prev = path[ prev ]; 105 | } 106 | cout<< src << endl; 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /9-System-Design-And-Scalability/2-Social-Networks/bfs.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Breadth First Traversal (or Search) for a graph is similar to Breadth First Traversal 3 | of a tree. The only catch here is, unlike trees, graphs may contain cycles, so we may 4 | come to the same node again. To avoid processing a node more than once, we use visited 5 | hash table. For simplicity, it is assumed that all vertices are reachable from the starting 6 | vertex. 7 | */ 8 | 9 | 10 | /* To compile use 'g++ bfs.cpp -o --std=c++11' */ 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | using std::cout; 18 | using std::endl; 19 | using std::list; 20 | using std::vector; 21 | using std::unordered_map; 22 | using std::queue; 23 | 24 | class Graph { 25 | public: 26 | list< int > vertices; 27 | vector< vector< int > > edges; // adjacency list 28 | 29 | Graph( int noOfVertices ) { 30 | edges.resize( noOfVertices ); 31 | } 32 | 33 | void bfs( int source ) { 34 | unordered_map visited( vertices.size() ); 35 | for( int i = 0; i < vertices.size(); i++ ) { 36 | visited[ i ] = false; 37 | } 38 | 39 | queue< int > toVisitQueue; 40 | toVisitQueue.push( source ); 41 | visited[ source ] = true; 42 | 43 | while( !toVisitQueue.empty() ) { 44 | int vertex = toVisitQueue.front(); 45 | toVisitQueue.pop(); 46 | cout<< ":" << vertex << endl; 47 | 48 | for( auto v : edges[ vertex ] ) { 49 | if( !visited[ v ] ) { 50 | toVisitQueue.push( v ); 51 | visited[ v ] = true; 52 | } 53 | } 54 | } 55 | } 56 | 57 | }; 58 | 59 | int main() { 60 | /* 61 | Example graph: 62 | 0 63 | / \ 64 | / \ 65 | / \ 66 | 1 2 67 | |\ | 68 | | \ | 69 | | \ | 70 | | \ | 71 | 3------- 4 72 | \ / 73 | \ / 74 | 5 75 | */ 76 | 77 | int noOfVertices = 6; 78 | /* create a graph */ 79 | Graph graph( noOfVertices ); 80 | for( int i = 0; i < noOfVertices; i++ ) { 81 | // add vertices 82 | graph.vertices.push_back( i ); 83 | } 84 | // add edges 85 | graph.edges[ 0 ].push_back(1); 86 | graph.edges[ 0 ].push_back(2); 87 | graph.edges[ 1 ].push_back(0); 88 | graph.edges[ 1 ].push_back(3); 89 | graph.edges[ 1 ].push_back(4); 90 | graph.edges[ 2 ].push_back(0); 91 | graph.edges[ 2 ].push_back(4); 92 | graph.edges[ 3 ].push_back(1); 93 | graph.edges[ 3 ].push_back(4); 94 | graph.edges[ 3 ].push_back(5); 95 | graph.edges[ 4 ].push_back(1); 96 | graph.edges[ 4 ].push_back(2); 97 | graph.edges[ 4 ].push_back(3); 98 | graph.edges[ 4 ].push_back(5); 99 | graph.edges[ 5 ].push_back(3); 100 | graph.edges[ 5 ].push_back(5); 101 | 102 | graph.bfs( 0 ); 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /4-Trees-and-Graphs/PathWithSum.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Paths with Sum: 3 | You are given a binary tree in which each node contains an integer value ( which 4 | might be positive or negative ). Design an algorithm to count the number of paths 5 | that sum to a given value. The path does not need to start or end at the root or 6 | a leaf, but it must go downwards (traveling only from parent nodes to child nodes). 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | using namespace std; 13 | 14 | class Node { 15 | public: 16 | int key; 17 | Node *left; 18 | Node *right; 19 | 20 | Node( int _key ) { 21 | key = _key; 22 | left = NULL; 23 | right = NULL; 24 | } 25 | }; 26 | 27 | void pathWithSum( Node *node, map sumMap, int tgtSum ) { 28 | int sum = 0; 29 | map::iterator it; 30 | for( it = sumMap.begin(); it != sumMap.end(); it++ ) { 31 | // Iterate through all paths and check if sum == tgtSum 32 | // also update the new sum and add this node as new starting path 33 | sum = node->key + it->second; 34 | if( sum == tgtSum ) { 35 | // target sum is reached, print the path 36 | cout<< "Start node: " << it->first->key << " end node: " << node->key << endl; 37 | } 38 | sumMap[ it->first ] = sum; 39 | // start a new path starting at this node 40 | sumMap[ node ] = node->key; 41 | } 42 | if( node->left ) 43 | pathWithSum( node->left, sumMap, tgtSum ); 44 | if( node->right ) 45 | pathWithSum( node->right, sumMap, tgtSum ); 46 | } 47 | 48 | void pathWithSum( Node *root, int sum ) { 49 | map< Node*, int > sumMap; 50 | sumMap[ root ] = root->key; 51 | 52 | if( root->key == sum ) { 53 | cout<< "Sum " << sum << " start node " << root << " end node " << root << endl; 54 | } 55 | 56 | if( root->left ) 57 | pathWithSum( root->left, sumMap, sum ); 58 | if( root->right ) 59 | pathWithSum( root->right, sumMap, sum ); 60 | } 61 | 62 | int main() { 63 | /* Example Tree 64 | 65 | 10 66 | / \ 67 | 5 -3 68 | / \ \ 69 | 3 2 11 70 | / \ \ 71 | 3 -2 1 72 | 73 | Solution: 74 | While traversing the tree we keep track of map, which is a 75 | mapping from starting node and sum from that node till the current node. 76 | 77 | At each node, we update this map by adding node->key to sum value and adding 78 | a new entry for sum starting at this node. 79 | 80 | We also check if the sum has the target, if so, we print the start node and 81 | this node. 82 | */ 83 | 84 | Node *root = new Node(10); 85 | root->right = new Node( -3 ); 86 | root->right->right = new Node( 11 ); 87 | 88 | root->left = new Node( 5 ); 89 | root->left->left = new Node( 3 ); 90 | root->left->right = new Node( 2 ); 91 | root->left->left->left = new Node( 3 ); 92 | root->left->left->right = new Node( -2 ); 93 | root->left->right->right = new Node( 1 ); 94 | 95 | pathWithSum( root, 8 ); 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /3-Stacks-And-Queues/AnimalShelter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | An animal shelter, which holds only dogs and cats, operates on a strictly 3 | first in, first out basis. People must adopt either the "oldest" ( based on 4 | arrival time ) of all animals at the shelter, or they can select whether they 5 | would prefer a dog or a cat ( and will receive the oldest animal of that type). 6 | They cannot select which specific animal they would like. Create the data structures 7 | to maintain this system and implement operations such as enqueue, dequeueAny, 8 | dequeueDog, and dequeueCat. You may use the built-in Linked List data structure. 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | class Animal { 17 | private: 18 | int id; 19 | int order; 20 | public: 21 | int getOrder() { return order; } 22 | void setOrder( int _order ) { order = _order; } 23 | void setId( int _id ) { id = _id; } 24 | int getId() { 25 | return id; 26 | } 27 | }; 28 | 29 | class Dog : public Animal { 30 | public: 31 | Dog() { setId( 1 ); } 32 | }; 33 | 34 | class Cat : public Animal { 35 | public: 36 | Cat() { setId( 2 ); } 37 | }; 38 | 39 | class AnimalQueue { 40 | public: 41 | AnimalQueue() { timestamp = 0; } 42 | void enqueue( Animal *animal ) { 43 | timestamp++; 44 | animal->setOrder( timestamp ); 45 | 46 | if( animal->getId() == 1 ) 47 | dogQueue.push( ( Dog * ) animal ); 48 | else 49 | catQueue.push( ( Cat * ) animal ); 50 | } 51 | 52 | Animal * dequeueAny() { 53 | if( catQueue.empty() and dogQueue.empty() ) 54 | return NULL; 55 | 56 | Animal *animal = NULL; 57 | if( not catQueue.empty() and not dogQueue.empty() ) { 58 | if( catQueue.front()->getOrder() > dogQueue.front()->getOrder() ) { 59 | animal = catQueue.front(); 60 | catQueue.pop(); 61 | } else { 62 | animal = dogQueue.front(); 63 | dogQueue.pop(); 64 | } 65 | } 66 | if( catQueue.empty() ) { 67 | animal = dogQueue.front(); 68 | dogQueue.pop(); 69 | } else { 70 | animal = catQueue.front(); 71 | catQueue.pop(); 72 | } 73 | return animal; 74 | } 75 | 76 | Dog * dequeueDog() { 77 | Dog *dog = NULL; 78 | if( not dogQueue.empty() ) { 79 | dog = dogQueue.front(); 80 | dogQueue.pop(); 81 | } 82 | return dog; 83 | } 84 | 85 | Cat * dequeueCat() { 86 | Cat *cat = NULL; 87 | if( not catQueue.empty() ) { 88 | cat = catQueue.front(); 89 | catQueue.pop(); 90 | } 91 | return cat; 92 | } 93 | 94 | private: 95 | int timestamp; 96 | queue dogQueue; 97 | queue catQueue; 98 | }; 99 | 100 | int main() { 101 | AnimalQueue aq; 102 | aq.enqueue( new Dog() ); 103 | aq.enqueue( new Cat() ); 104 | aq.dequeueCat(); 105 | aq.dequeueDog(); 106 | 107 | aq.enqueue( new Dog() ); 108 | aq.enqueue( new Cat() ); 109 | aq.dequeueAny(); 110 | aq.dequeueAny(); 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /2-Linked-Lists/SumList.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | You have two numbers represented by a linked list, where each node contains a single 3 | digit. The digits are stored in reverse order, such that the 1 's digit is at the head 4 | of the list. 5 | 6 | Write a function that adds the two numbers and returns the sum as a linked list. 7 | 8 | EXAMPLE 9 | Input: ( 7->1->6) + (5->9->2) .That is, 617 + 295. 10 | 11 | Output: 2->1->9. That is, 912. 12 | 13 | FOLLOW UP 14 | Suppose the digits are stored in forward order. Repeat the above problem. 15 | */ 16 | 17 | #include 18 | 19 | using namespace std; 20 | 21 | class Node { 22 | private: 23 | int data_; 24 | Node *next_; 25 | public: 26 | Node( int _data ) : data_( _data ), next_( NULL ) {} 27 | ~Node() { next_ = NULL; } 28 | Node * next() { return this->next_; } 29 | int data() { return data_; } 30 | void dataIs( int _data ) { data_ = _data; } 31 | void nextIs( Node *node ) { this->next_ = node; } 32 | }; 33 | 34 | void addFront( Node *head, int data ) { 35 | Node *newNode = new Node( data ); 36 | newNode->nextIs( head->next() ); 37 | head->nextIs( newNode ); 38 | } 39 | 40 | void printLL( Node *node ) { 41 | while( node != NULL ) { 42 | cout<< node->data() << "->"; 43 | node = node->next(); 44 | } 45 | cout << endl; 46 | } 47 | 48 | Node * sumLL( Node *l1, Node *l2 ) { 49 | Node *l3 = NULL; 50 | Node *curr = NULL; 51 | Node *newNode; 52 | 53 | int carry = 0; 54 | int sum = 0; 55 | 56 | while( l1 != NULL && l2 != NULL ) { 57 | 58 | sum = l1->data() + l2->data() + carry; 59 | if( sum > 9 ) 60 | carry = 1; 61 | else 62 | carry = 0; 63 | 64 | newNode = new Node( sum % 10 ); 65 | if( curr == NULL ) { 66 | curr = newNode; 67 | l3 = curr; // result head 68 | } else { 69 | curr->nextIs( newNode ); 70 | curr = curr->next(); 71 | } 72 | 73 | l1 = l1->next(); 74 | l2 = l2->next(); 75 | } 76 | 77 | if( l1 == NULL ) 78 | l1 = l2; 79 | 80 | while( l1 != NULL ) { 81 | sum = l1->data() + carry; 82 | if( sum > 9 ) 83 | carry = 1; 84 | else 85 | carry = 0; 86 | 87 | newNode = new Node( sum % 10 ); 88 | curr->nextIs( newNode ); 89 | curr = curr->next(); 90 | l1 = l1->next(); 91 | } 92 | return l3; 93 | } 94 | 95 | int main() { 96 | // keep head as a dummy Node 97 | cout<< "Sum of 2 link list (1 's digit is at the head of the list)" << endl; 98 | Node *head1 = new Node( -1 ); 99 | 100 | // create a LL 101 | addFront( head1, 8 ); 102 | addFront( head1, 2 ); 103 | addFront( head1, 4 ); 104 | 105 | Node *head2 = new Node( -1 ); 106 | addFront( head2, 6 ); 107 | addFront( head2, 0 ); 108 | addFront( head2, 4 ); 109 | addFront( head2, 8 ); 110 | 111 | // print Linked List 112 | printLL( head1->next() ); 113 | printLL( head2->next() ); 114 | 115 | Node *sum = sumLL( head1->next(), head2->next() ); 116 | cout<< "Sum:" << endl; 117 | printLL( sum ); 118 | return 0; 119 | } 120 | -------------------------------------------------------------------------------- /17-Hard/5-Letters-And-Numbers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Letters and Numbers: 3 | Given an array filled with letters and numbers, find the longest subarray with an equal 4 | number of letters and numbers. 5 | 6 | All letters are treated identically and all numbers are treated identically. Therefore, 7 | we can use an example with a single letter and a single number -or, for that matter, 8 | As and Bs, Os and 1s. 9 | Example: [ A, B, A, A, A, B, B, B, A, B, A, A, B, B, A, A, A, A, A, A ] 10 | 11 | We're looking for the smallest subarray where count( A, subarray ) = count( B, subarray ). 12 | 13 | Brute Force: 14 | Just go through all subarrays, count the number of As and Bs (or letters and numbers), and 15 | find the longest one that is equal. We can make one small optimization to this. We can start 16 | with the longest subarray and, as soon as we find one which fits this equality condition, return it. 17 | O( N^2 ). 18 | 19 | Optimal Solution: 20 | 21 | A, B, A, A, A, B, B, B, A, B, A, A, B, B, A, A, A, A, A, A 22 | count A: 1 1 2 3 4 4 4 4 5 5 6 7 7 7 8 9 10 11 12 13 23 | count B: 0 1 1 1 1 2 3 4 4 5 5 5 6 7 7 7 7 7 7 7 24 | Diff: 1 0 1 2 3 2 1 0 1 0 1 2 1 0 1 2 3 4 5 6 25 | 26 | 27 | Whenever we return the same difference, then we know we have found an equal subarray. To find the 28 | biggest subarray, we just have to find the two indices farthest apart with the same value. 29 | 30 | Alternate Solution: 31 | Replace A with 1 and B with -1. Use kudane algo to find longest array with 0 sum. 32 | 33 | */ 34 | 35 | // g++ 5-Letters-And-Numbers.cpp --std=c++11 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | using std::cout; 42 | using std::endl; 43 | using std::vector; 44 | using std::unordered_map; 45 | 46 | vector computeDelta( vector arr ) { 47 | int onesCount = 0; 48 | int zerosCount = 0; 49 | vector diff( arr.size() ); 50 | for( int i=0; i < arr.size(); ++i ) { 51 | if( arr[i] == 1 ) { 52 | ++onesCount; 53 | } else { 54 | ++zerosCount; 55 | } 56 | diff[i] = onesCount - zerosCount; 57 | } 58 | return diff; 59 | } 60 | 61 | std::pair findLongesMatch( vector delta ) { 62 | std::pair max = std::make_pair( 0, 0 ); 63 | unordered_map map; 64 | map.insert( std::make_pair( 0, -1) ); // diff = 0 initially 65 | for( int i = 0; i < delta.size(); ++i ) { 66 | if( map.find( delta[i] ) == map.end() ) { 67 | map.insert( std::make_pair( delta[i], i ) ); 68 | } else { 69 | int index = map[ delta[i] ]; 70 | int dist = i - index; 71 | if( dist > max.second - max.first ) { 72 | max = std::make_pair( index, i ); 73 | } 74 | } 75 | } 76 | return max; 77 | } 78 | 79 | std::pair getMaxSubArrayWithSameAandB( vector arr ) { 80 | vector delta = computeDelta( arr ); 81 | std::pair max = findLongesMatch( delta ); 82 | return max; 83 | } 84 | 85 | int main() { 86 | vector arr = { 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }; 87 | getMaxSubArrayWithSameAandB( arr ); 88 | return 0; 89 | } 90 | --------------------------------------------------------------------------------