├── .github └── README_solution.md ├── .gitignore ├── 00_Arrays ├── ContainsDuplicate │ ├── C++ │ │ ├── Makefile │ │ └── main.cc │ ├── JS │ │ └── solution.js │ ├── README.md │ └── python │ │ └── Solution.py ├── Count-the-number-of-occurrences-in-a-sorted-array │ ├── Makefile │ ├── README.md │ └── solution_divideAndConquer.c ├── FirstAndSecondSmallest │ ├── README.md │ └── Solution.py ├── MaxMin │ ├── README.md │ └── Solution.java ├── MaximumSubArray │ ├── JS │ │ ├── DivideAndConquer.js │ │ └── Kadane.js │ ├── Java │ │ ├── BackToBackSWESolution.java │ │ ├── MaximumSubArray.java │ │ └── MaximumSubArrayTest.java │ └── README.md ├── MedianMaintenance │ └── src │ │ ├── Main.kt │ │ └── README.md ├── MostFrequentInteger │ ├── README.md │ └── Solution.py ├── Permutation │ ├── Permutation.java │ └── README.md ├── README.md ├── RemoveDuplicatesFromSortedArray │ ├── C++ │ │ └── Solution.cpp │ ├── Java │ │ └── Solution.java │ └── README.md ├── SegregatePositiveAndNegativeNumbers │ ├── README.md │ └── python │ │ └── solution.py ├── best-time-to-buy-and-sell-stock │ ├── README.md │ └── solution.js ├── containsSum │ ├── C++ │ │ ├── Makefile │ │ ├── main │ │ └── main.cc │ ├── README.md │ └── Solution.java ├── coupleSum │ ├── README.md │ ├── Solution.java │ └── solution.js ├── find-minimum-in-rotated-sorted-array │ ├── README.md │ └── solution.js ├── insert-interval │ ├── README.md │ └── solution.js ├── kLargestNumbers │ ├── README.md │ └── Solution.java ├── maximum-product-subarray │ ├── README.md │ └── solution.js ├── merge-intervals │ ├── README.md │ └── solution.js ├── product-of-array-except-self │ ├── README.md │ └── solution.js ├── rotate-image │ ├── README.md │ └── solution.js ├── set-matrix-zeroes │ ├── README.md │ └── solution.js ├── spiralOrderMatrix │ ├── Readme.md │ └── Solution.java └── transposeMatrix │ ├── README.md │ └── solution.js ├── 01_Strings ├── FindTheFirstNonRepetitiveChar │ ├── README.md │ ├── Solution.kt │ └── Solution.py ├── Permutation │ ├── README.md │ ├── Solution.java │ └── Solution.py ├── README.md ├── StringReverseInPlace │ └── StringReverseInPlace.java ├── checkForUniqueCharacters │ ├── README.md │ └── Soultion.py ├── isAnagram │ ├── README.md │ ├── Solution.py │ └── solution.js ├── isPalindrome │ ├── README.md │ └── Solution.py ├── longest-substring-without-repeating-characters │ ├── README.md │ └── solution.js └── shortestPalindrome │ ├── README.md │ └── Solution.py ├── 02_LinkedLists ├── LoopInList │ ├── README.md │ ├── helperFuncs.cpp │ └── main.cpp ├── README.md ├── ReverseLinkedList │ ├── README.md │ ├── ReverseList.java │ └── ReverseList.py ├── SortList │ ├── README.md │ └── Solution.java ├── add-two-numbers │ ├── README.md │ └── solution.js ├── delAtPosition │ ├── README.md │ └── Solution.java ├── doubleLinkDel │ └── Solution.java ├── isPalindrome │ ├── README.md │ ├── Solution.java │ └── solution.js ├── merge-k-sorted-lists │ ├── README.md │ └── solution.js ├── merge-two-sorted-lists │ ├── README.md │ └── solution.js └── reverse-linked-list │ ├── README.md │ └── solution.js ├── 03_Stacks_and_Queues ├── Has_redundats(s) │ ├── README.md │ ├── has_redundant(s).py │ └── main.py ├── MissingNoFromStack │ └── MissingNoFromStack.java ├── Queue │ ├── README.md │ └── queue.py ├── QueueUsingStack │ └── QueueUsingStack.java ├── README.md ├── Stack │ ├── Stack.java │ └── stack.py └── minElementInStack │ ├── README.md │ ├── Stack.py │ └── minStack.py ├── 04_Trees_and_Graphs ├── README.md ├── countTheLeaves │ ├── README.md │ └── Solution.java ├── hasPathSum │ ├── README.md │ └── Solution.java ├── invert-binary-tree │ ├── README.md │ └── solution.js ├── isBST │ ├── README.md │ ├── Solution.java │ └── solution.js ├── isBalanced │ ├── README.md │ └── Solution.java ├── levelOrderTraversal │ ├── README.md │ └── Solution.java ├── maximum-depth-of-binary-tree │ └── README.md ├── numberOfIslands │ ├── README.md │ └── Solution.java ├── pathSum2 │ ├── README.md │ └── solution.js ├── projectDependencies │ ├── README.md │ └── Solution.java ├── sameLevel │ ├── README.md │ └── Solution.java ├── sameTree │ ├── README.md │ ├── Solution.java │ └── solution.js └── subtree-of-another-tree │ ├── README.md │ └── solution.js ├── 05_Bit_Manipulation ├── AddBinary │ ├── README.md │ └── solution.js ├── Basics │ ├── README.md │ └── main.cpp ├── CountThe1-s │ ├── README.md │ └── main.swift ├── Merge-Two-Sorted-Arrays │ ├── README.md │ └── main.c ├── Minimum-Of-Two-Integers │ ├── README.md │ ├── main.cpp │ └── main.swift ├── Modular-Addition │ ├── README.md │ ├── main.cpp │ └── main.swift ├── NextPowerof2 │ ├── NextPowerOf2.swift │ └── ReadME.md ├── README.md ├── Subsets │ ├── README.md │ └── Subsets.java ├── Swap │ ├── README.md │ ├── main.cpp │ └── main.swift └── bit_hacks.pdf ├── 06_Math_and_Logic_Puzzles └── README.md ├── 07_Object-Oriented_Design ├── README.md └── Url_shortner │ ├── README.md │ └── url_shortner.py ├── 08_Recursion_and_Dynamic_Programming ├── CuttingRod │ ├── README.md │ ├── cuttingRod.java │ └── cuttingRodTest.java ├── EditDistance │ ├── README.md │ └── Solution.py ├── Fibonacci_Number │ ├── README.md │ └── fib.py ├── Hanoi │ ├── ReadMe.md │ └── Solution.java ├── MobileNumericKeypadProblem │ ├── README.md │ └── solution.py ├── Permutations │ ├── README.md │ └── permutations.py ├── README.md ├── SubsetsGeneration │ ├── README.md │ └── solution.py ├── Ugly_Numbers │ ├── README.md │ └── uglynumbers.py ├── WaysToWriteN │ ├── DynamicSolution.java │ ├── Readme.md │ └── RecusiveSolution.java ├── coinChanger │ ├── README.md │ ├── Solution.java │ └── solution.py ├── kthPermutation │ ├── README.md │ └── kthPermutation.py └── longestGeometricProgression │ ├── README.md │ └── solution.py ├── 09_System_Design_and_Scalability ├── Heap │ ├── MinHeap.py │ └── README.md └── README.md ├── 10_Sorting_and_Searching └── README.md ├── 11_Testing └── README.md ├── 12_Language_Based_Questions ├── Android_Questions.md ├── JavaScript_Questions.md ├── Java_questions.md ├── Python.md ├── README.md ├── cpp_questions.md └── web_dev.md ├── 13_Misc ├── BasicArithmetic.java ├── LetterInOrder │ ├── README.md │ └── Solution.py ├── Must-Read-Links.md ├── README.md ├── ReverseInteger │ ├── README.md │ ├── Solution.java │ └── Solution.py ├── ThreadExample.java ├── TopCoder │ └── src │ │ ├── businessTasks │ │ ├── BusinessTasks.java │ │ └── BusinessTasksTest.java │ │ ├── cardStraights │ │ ├── CardStraights.java │ │ └── CardStraightsTest.java │ │ ├── hotel │ │ ├── Hotel.java │ │ └── HotelTest.java │ │ ├── poetry │ │ └── Poetry.java │ │ ├── smartWordToy │ │ └── SmartWordToy.java │ │ └── tallPeople │ │ └── TallPeople.java ├── bday-celebration.java └── megaPrep.pdf ├── CheatSheets ├── BigOCheatSheet.jpg └── README.md └── README.md /.github/README_solution.md: -------------------------------------------------------------------------------- 1 | # Folder name 2 | ## Question 3 | ``` 4 | Question description 5 | ``` 6 | 7 | 8 | ## Techniques: 9 | * technique 1 10 | * technique 2 11 | 12 | -------------------------------------------------------------------------------- /00_Arrays/ContainsDuplicate/C++/Makefile: -------------------------------------------------------------------------------- 1 | CC := gcc 2 | CFLAGS := -O0 -g -std=c99 -Wall -Wextra -Wshadow -pedantic -Werror 3 | CXXFLAGS := -O0 -g -std=c++11 -Wall -Wextra -Wshadow -pedantic -Weffc++ -Werror 4 | -------------------------------------------------------------------------------- /00_Arrays/ContainsDuplicate/C++/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | bool containsDuplicate(int nums[], size_t size, size_t k) { 6 | std::unordered_map m; 7 | for(size_t i=0; i < size; i++) { 8 | if(m.find(nums[i]) == m.end()) { 9 | // new element 10 | m[ nums[i] ] = i; 11 | } 12 | else { 13 | size_t prev_index = m[ nums[i] ]; 14 | if ( (i - prev_index) <= k ) return true; 15 | else m[ nums[i] ] = i; 16 | } 17 | } 18 | return false; 19 | } 20 | 21 | int main(void) 22 | { 23 | int arr[] = {1, 2, 7, 2, 3, 4}; 24 | size_t n = sizeof(arr)/sizeof(arr[0]); 25 | assert(containsDuplicate(arr, n, 2) == true); 26 | assert(containsDuplicate(arr, n, 1) == false); 27 | std::cout << "Assers Passed" << std::endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /00_Arrays/ContainsDuplicate/JS/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {boolean} 4 | */ 5 | 6 | // O(n log n) (sorting) 7 | var containsDuplicateSort = function(nums) { 8 | // modifying the original array, we could also have made a copy 9 | nums.sort((a, b) => a - b) 10 | // check if an array elements are equal next to each other 11 | // note that the limit is nums.length - 1 12 | for (let i=1; i < nums.length - 1; i++) { 13 | if (nums[i] === nums[i - 1]) return true 14 | } 15 | return false 16 | }; 17 | 18 | // O(n) (hash-set) 19 | var containsDuplicate = function(nums) { 20 | const set = new Set() 21 | // add to set if it is not present already 22 | // if it was present we have found a duplicate 23 | for (let i=0; i < nums.length; i++) { 24 | if (set.has(nums[i])) return true 25 | set.add(nums[i]) 26 | } 27 | return false 28 | }; 29 | -------------------------------------------------------------------------------- /00_Arrays/ContainsDuplicate/README.md: -------------------------------------------------------------------------------- 1 | # Contains Duplicate 2 | 3 | `Easy` 4 | 5 | Given an array of integers, find if the array contains any duplicates. 6 | 7 | Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct. 8 | 9 | ## Example 1: 10 | 11 | ``` 12 | Input: [1,2,3,1] 13 | Output: true 14 | ``` 15 | 16 | ## Example 2: 17 | ``` 18 | Input: [1,2,3,4] 19 | Output: false 20 | ``` 21 | 22 | ## Example 3: 23 | 24 | ``` 25 | Input: [1,1,1,3,3,4,3,2,4,2] 26 | Output: true 27 | ``` 28 | 29 | ## Complexity Analysis (sorting approach): 30 | 31 | - **Time complexity** : `O(n log n)`. Sorting is the expensive part. The iteration/sweeping otherwise happens in `O(n)` 32 | 33 | - **Space complexity** : **`O(1)`**. If `heapsort` is used, space complexity will be `O(1)` 34 | 35 | ## Complexity Analysis (HashSet approach): 36 | 37 | - **Time complexity** : **`O(n))`**. We do `has()` and `add()` operations on the hash-set for `n` times and each operation takes constant time. 38 | 39 | - **Space complexity** : `O(n)`. The space complexity of the Hash-Set with max of `n` items. 40 | 41 | ## Note 42 | 43 | For certain test cases with not very large `n`, the runtime of **HashSet approach can be slower than sorting approach**. The reason is hash table has some overhead in maintaining its property. One should keep in mind that real world performance can be different from what the Big-O notation says. The Big-O notation only tells us that for sufficiently large input, one will be faster than the other. Therefore, when `n` is not sufficiently large, an `O(n)` algorithm can be slower than an `O(n log n)` algorithm. 44 | 45 | #### [LeetCode link](https://leetcode.com/problems/contains-duplicate/) 46 | -------------------------------------------------------------------------------- /00_Arrays/ContainsDuplicate/python/Solution.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def containsNearbyDuplicate(self, nums, k): 3 | """ 4 | :type nums: List[int] 5 | :type k: int 6 | :rtype: bool 7 | < = k 8 | """ 9 | if len(nums) == 1: 10 | return False 11 | hm = {} # key element value index 12 | for i in range(len(nums)): 13 | if not nums[i] in hm: 14 | #new element 15 | hm[nums[i]] = i 16 | else: 17 | prev_index = hm[nums[i]] 18 | if i - prev_index <= k: 19 | return True 20 | else: 21 | hm[nums[i]] = i 22 | return False 23 | 24 | 25 | -------------------------------------------------------------------------------- /00_Arrays/Count-the-number-of-occurrences-in-a-sorted-array/Makefile: -------------------------------------------------------------------------------- 1 | CC := gcc 2 | CFLAGS := -O0 -g -std=c99 -Wall -Wextra -Wshadow -pedantic -Werror 3 | CXXFLAGS := -O0 -g -std=c++11 -Wall -Wextra -Wshadow -pedantic -Weffc++ -Werror 4 | clean: 5 | rm -f *.exe 6 | echo Clean done -------------------------------------------------------------------------------- /00_Arrays/Count-the-number-of-occurrences-in-a-sorted-array/README.md: -------------------------------------------------------------------------------- 1 | Count the number of occurrences in a sorted array 2 | ``` 3 | Given a sorted array arr[] and a number x, 4 | write a function that counts the occurrences of x in arr[]. 5 | ``` 6 | 7 | [Source](http://goo.gl/4cpGcs) 8 | 9 | Time Complexity: O(Logn) 10 | 11 | Programming Paradigm: Divide & Conquer 12 | 13 | ## Solution 14 | 15 | 1. Use Binary search to get index of the first occurrence of x in arr[]. Let the index of the first occurrence be i. 16 | 2. Use Binary search to get index of the last occurrence of x in arr[]. Let the index of the last occurrence be j. 17 | 3. Return (j – i + 1 18 | 19 | - [Binary search in Java by princeton](http://algs4.cs.princeton.edu/11model/BinarySearch.java.html) 20 | 21 | ## NOTE 22 | 23 | ``` 24 | Instead of mid=(hi+lo)/2 25 | 26 | Write, mid=lo+(hi-lo)/2 27 | ``` 28 | 29 | - [To avoid overflow!](http://stackoverflow.com/questions/25571359/why-we-write-lohi-lo-2-in-binary-search) 30 | - [Google also says that](http://googleresearch.blogspot.fr/2006/06/extra-extra-read-all-about-it-nearly.html) 31 | 32 | -------------------------------------------------------------------------------- /00_Arrays/Count-the-number-of-occurrences-in-a-sorted-array/solution_divideAndConquer.c: -------------------------------------------------------------------------------- 1 | /* 2 | Count the number of occurrences in a sorted array 3 | Given a sorted array arr[] and a number x, 4 | write a function that counts the occurrences of x in arr[]. 5 | 6 | http://goo.gl/4cpGcs 7 | 8 | Time Complexity: O(Logn) 9 | Programming Paradigm: Divide & Conquer 10 | */ 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | int binarySearch(int arr[], int x, size_t n, bool isFirst); 17 | 18 | /* if x is present in arr[] then returns the count of occurrences of x, 19 | otherwise returns -1. */ 20 | int count(int arr[], int x, size_t n) 21 | { 22 | int i; // index of first occurrence of x in arr[0..n-1] 23 | int j; // index of last occurrence of x in arr[0..n-1] 24 | 25 | /* get the index of first occurrence of x */ 26 | i = binarySearch(arr, x, n, true); 27 | 28 | /* If x doesn't exist in arr[] then return -1 */ 29 | if(i == -1) 30 | return i; 31 | 32 | /* Else get the index of last occurrence of x. */ 33 | j = binarySearch(arr, x, n, false); 34 | 35 | /* return count */ 36 | return j-i+1; 37 | } 38 | 39 | int binarySearch(int arr[], int x, size_t n, bool isFirst) 40 | { 41 | size_t low = 0; 42 | size_t high = n-1; 43 | size_t result = -1; // initialise result to -1 44 | while(low <= high) 45 | { 46 | int mid = low + (high - low)/2; 47 | if (arr[mid] == x) { 48 | result = mid; 49 | if(isFirst) high = mid-1; // need first occurence 50 | else low = mid+1; // need second occurence 51 | } 52 | else if(x > arr[mid]) 53 | low = mid + 1; 54 | else 55 | high = mid - 1; 56 | } 57 | return result; 58 | } 59 | 60 | /* driver program to test above functions */ 61 | int main() 62 | { 63 | int arr[] = {1, 2, 2, 3, 3, 3, 3}; 64 | int x = 3; // Element to be counted in arr[] 65 | size_t n = sizeof(arr)/sizeof(arr[0]); 66 | int c = count(arr, x, n); 67 | printf(" \"%d\" occurs %d times ", x, c); 68 | getchar(); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /00_Arrays/FirstAndSecondSmallest/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | Write an efficient C program to find smallest and second smallest element in an array. 3 | 4 | ``` -------------------------------------------------------------------------------- /00_Arrays/FirstAndSecondSmallest/Solution.py: -------------------------------------------------------------------------------- 1 | # your code goes here 2 | import sys 3 | def findTheTwoSmallest(arr): 4 | l = len(arr) 5 | if l <= 2: 6 | return arr 7 | second = first = sys.maxint 8 | for i in range(l): 9 | if arr[i] < first: 10 | second = first 11 | first = arr[i] 12 | elif arr[i] < second: 13 | second = arr[i] 14 | return first, second 15 | 16 | def findTheTwoSmallestIndex(arr): 17 | l = len(arr) 18 | if l <= 2: 19 | return arr 20 | second = first = 0 21 | for i in range(1, l): 22 | if arr[i] < arr[first]: 23 | second = first 24 | first = i 25 | elif arr[i] < arr[second]: 26 | second = i 27 | return first, second 28 | 29 | 30 | 31 | print findTheTwoSmallest([1, 2, 3, 4, 5, 0]) 32 | print findTheTwoSmallestIndex([1, 2, 3, 4, 5, 0]) 33 | -------------------------------------------------------------------------------- /00_Arrays/MaxMin/README.md: -------------------------------------------------------------------------------- 1 | ## Find Maximum and Minimum in an array. 2 | 3 | #### First Solution: 4 | ``` 5 | Traverse through the array to get the minimum element. (Time Complexity - O(n); Number of comparitions: n-2) 6 | Traverse second time to get the maximum element. (Time Complexity - O(n); number of comparitions: n-2) 7 | ``` 8 | 9 | #### Second Solution: 10 | Let us consider 4 elements x1, x2, x3, x4 11 | 12 | ![maxmin diagram](https://cloud.githubusercontent.com/assets/3127498/17457773/331e1bc6-5bcf-11e6-8bd3-1645cec1988b.png) 13 | 14 | The maximum and minimum can be obtained by just 4 comparitions for 4 elements. 15 | 16 | Strategy used: **Divide and Conquer** 17 | 18 | **Time Complexity: 3n/2 - 2** 19 | 20 | source: 21 | [Design & Analysis of Algorithms by Prof.Abhiram Ranade](http://www.nptelvideos.in/2012/11/design-analysis-of-algorithms.html) 22 | 23 | [Working example of source code(I am not sure if it is a permenent link. just copy paste in Ideone.com and it will work fine)](https://ideone.com/YyCbiR) 24 | -------------------------------------------------------------------------------- /00_Arrays/MaxMin/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.lang.*; 3 | import java.io.*; 4 | class Pair { 5 | Pair() { 6 | 7 | } 8 | Pair(int min, int max) { 9 | this.min = min; 10 | this.max = max; 11 | } 12 | 13 | @Override 14 | public String toString() { 15 | StringBuilder sb = new StringBuilder(); 16 | sb.append("Min :").append(min); 17 | sb.append(" Max :").append(max); 18 | return sb.toString(); 19 | } 20 | 21 | public int min, max; 22 | } 23 | 24 | 25 | /* Name of the class has to be "Main" only if the class is public. */ 26 | class Ideone 27 | { 28 | 29 | public Pair findMinMax(int[] a, int left, int right) { 30 | if(left > right) return null; 31 | if(left == right) return new Pair(a[left], a[left]); 32 | if((right - left) == 1) { 33 | //only two elements 34 | if(a[left] > a[right]) { 35 | return new Pair(a[right], a[left]); 36 | } else { 37 | return new Pair(a[left], a[right]); 38 | } 39 | } 40 | // find left maxmin and right maxmin 41 | int mid = (left+right)/2; 42 | Pair leftmaxmin = findMinMax(a, left, mid); 43 | Pair rightmaxmin = findMinMax(a, mid+1, right); 44 | Pair result = new Pair(); 45 | if(leftmaxmin.min < rightmaxmin.min) 46 | result.min = leftmaxmin.min; 47 | else 48 | result.min = rightmaxmin.min; 49 | 50 | if(leftmaxmin.max > rightmaxmin.max) 51 | result.max = leftmaxmin.max; 52 | else 53 | result.max = rightmaxmin.max; 54 | 55 | return result; 56 | } 57 | public static void main (String[] args) throws java.lang.Exception 58 | { 59 | int[] a = {1, 2, 3, 4, 8, 7, 6, 5, 100, 0}; 60 | Ideone pgm = new Ideone(); 61 | Pair minmax = pgm.findMinMax(a, 0, a.length-1); 62 | // Pair minmax = new Pair(5,1); 63 | System.out.println(minmax); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /00_Arrays/MaximumSubArray/JS/DivideAndConquer.js: -------------------------------------------------------------------------------- 1 | // Find the maximum possible sum in nums[] auch that nums[mid] is part of it 2 | function maxCrossingSum(nums, left, mid, right) { 3 | let leftMaxCrossingMid = Number.MIN_SAFE_INTEGER 4 | let sum = 0 5 | // Include elements on left of mid. (including nums[mid] itself, since we start from nums[mid] it is always included) 6 | // at the very least will contain nums[mid].. when all are positive it will have nums[mid] to nums[left] 7 | for (let i=mid; i >= left; i--) { 8 | sum = sum + nums[i] 9 | leftMaxCrossingMid = Math.max(sum, leftMaxCrossingMid) 10 | } 11 | let rightMaxCrossingMid = Number.MIN_SAFE_INTEGER 12 | sum = 0 13 | // Include elements on right of mid. (starts from nums[mid + 1] itself, since we start from nums[mid + 1] it is always included) 14 | // at the very least will contain nums[mid + 1].. when all are positive it will have nums[mid + 1] to nums[right] 15 | for (let i=(mid + 1); i <= right; i++) { 16 | sum = sum + nums[i] 17 | rightMaxCrossingMid = Math.max(sum, rightMaxCrossingMid) 18 | } 19 | return leftMaxCrossingMid + rightMaxCrossingMid 20 | } 21 | 22 | function maxSubArrayHelper(nums, left, right) { 23 | // base case, only one element 24 | if (left === right) { 25 | return nums[left] 26 | } 27 | 28 | const mid = Math.trunc(left + (right - left) / 2) 29 | 30 | // Maximum subarray sum in left half 31 | const leftMax = maxSubArrayHelper(nums, left, mid) 32 | // Maximum subarray sum in right half 33 | const rightMax = maxSubArrayHelper(nums, mid + 1, right) 34 | // Maximum subarray sum such that the subarray crosses the midpoint 35 | const maxCrossingMid = maxCrossingSum(nums, left, mid, right) 36 | 37 | /* Return maximum of following three possible cases 38 | a) Maximum subarray sum in left half 39 | b) Maximum subarray sum in right half 40 | c) Maximum subarray sum such that the subarray crosses the midpoint 41 | */ 42 | return Math.max(leftMax, rightMax, maxCrossingMid) 43 | } 44 | 45 | var maxSubArray = function(nums) { 46 | return maxSubArrayHelper(nums, 0, nums.length - 1) 47 | }; -------------------------------------------------------------------------------- /00_Arrays/MaximumSubArray/JS/Kadane.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | var maxSubArray = function(nums) { 6 | // global maximum seen so far 7 | let maxSum = Number.MIN_SAFE_INTEGER 8 | // best max ending at previous array element (this is our subproblem) 9 | let prevSubArrayMaxSum = Number.MIN_SAFE_INTEGER 10 | nums.forEach(num => { 11 | /* 12 | We want to answer the question: 13 | "What is the Max Contiguous Subarray Sum we can achieve ending at index i?" 14 | 15 | We have 2 choices: 16 | 17 | prevSubArrayMaxSum + nums[i] (extend the previous subarray best whatever it was) 18 | 1.) Let the item we are sitting at contribute to this best max we achieved 19 | ending at index i - 1. 20 | 21 | 2.) Just take the item we are sitting at's value. 22 | 23 | The max of these 2 choices will be the best answer to the Max Contiguous SubArraySum ending at i index 24 | */ 25 | const currSubArrayMaxSum = Math.max(num, prevSubArrayMaxSum + num) 26 | maxSum = Math.max(maxSum, currSubArrayMaxSum) 27 | prevSubArrayMaxSum = currSubArrayMaxSum 28 | }) 29 | return maxSum 30 | }; -------------------------------------------------------------------------------- /00_Arrays/MaximumSubArray/Java/MaximumSubArray.java: -------------------------------------------------------------------------------- 1 | package maximumSubArray; 2 | 3 | public class MaximumSubArray { 4 | public static int brute(final int[] a, final int start, final int end) { // O(n^3) 5 | int n = a.length; 6 | int max = Integer.MIN_VALUE; 7 | for(int sub_array_size=1; sub_array_size<=n; sub_array_size++) { // for each sub-array size 8 | for(int start_index=0; start_index n) break; // subarray exceeds bounds 10 | int sum=0; 11 | for(int i=start_index; i n) break; // subarray exceeds bounds 26 | sum += a[start_index+sub_array_size-1]; /* Use the sum of previous subarray and add with last element of this subarray */ 27 | max = Math.max(sum, max); 28 | } 29 | } 30 | return max; 31 | } 32 | public static int divideAndConquer(final int[] a, final int start, final int end) { // O(nlgn) - https://www.youtube.com/watch?v=ohHWQf1HDfU 33 | if(start == end) 34 | return a[start]; 35 | final int mid = (start+end)/2; 36 | int leftMSS = divideAndConquer(a, start, mid); 37 | int rightMSS = divideAndConquer(a, mid+1, end); 38 | // max mid crossing subarray 39 | int sum = 0; 40 | int leftmax = Integer.MIN_VALUE; 41 | for(int i=mid; i>=start; i--) { // left side 42 | sum += a[i]; 43 | leftmax = Math.max(sum, leftmax); 44 | } 45 | sum = 0; 46 | int rightmax = Integer.MIN_VALUE; 47 | for(int i=mid+1; i<=end; i++) { 48 | sum += a[i]; 49 | rightmax = Math.max(sum, rightmax); 50 | } 51 | return Math.max(leftmax+rightmax, Math.max(leftMSS, rightMSS)); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /00_Arrays/MaximumSubArray/Java/MaximumSubArrayTest.java: -------------------------------------------------------------------------------- 1 | package maximumSubArray; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | public class MaximumSubArrayTest { 8 | final int[] clrs = new int[]{13,-3,-25,20,-3,-16,-23,18,20,-7,12,-5,-22,15,-4,7}; // pg 70 9 | @Test 10 | public void testBrute() { 11 | assertEquals(43, MaximumSubArray.brute(clrs, 0, clrs.length-1)); 12 | } 13 | 14 | @Test 15 | public void testBruteOptimal() { 16 | assertEquals(43, MaximumSubArray.bruteOptimal(clrs, 0, clrs.length-1)); 17 | } 18 | 19 | @Test 20 | public void testDivideAndConquer() { 21 | assertEquals(43, MaximumSubArray.divideAndConquer(clrs, 0, clrs.length-1)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /00_Arrays/MaximumSubArray/README.md: -------------------------------------------------------------------------------- 1 | ## Maximum Subarray 2 | 3 | ![Difficulty-Easy](https://img.shields.io/badge/Difficulty-Easy-green) 4 | 5 | ![Dynamic Programming or Divide and conquer Technique](https://img.shields.io/badge/Technique-Dynamic_Programming_or_Divide_and_conquer-blue) 6 | 7 | Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. 8 | 9 | ## Example: 10 | 11 | ``` 12 | Input: [-2,1,-3,4,-1,2,1,-5,4], 13 | Output: 6 14 | Explanation: [4,-1,2,1] has the largest sum = 6. 15 | ``` 16 | 17 | ## Follow up: 18 | 19 | If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle. 20 | 21 | #### [LeetCode Link](https://leetcode.com/problems/maximum-subarray/) 22 | 23 | ## Complexity Analysis (Dynamic Programming - Kadane): 24 | 25 | **See [JS Solution](JS/Kadane.js)** 26 | 27 | - **Time complexity** : `O(n) -- linear`. We sweep through the array once. 28 | 29 | - **Space complexity** : `O(1)`. Only two extra variables to keep the global-max-so-far and max-subarray-sum-for-subarray-ending-at-previous-element-of-thearray. 30 | 31 | ## Complexity Analysis (Divide and conquer): 32 | 33 | **See [JS Solution](JS/DivideAndConquer.js)** 34 | 35 | - **Time complexity** : `O(n * log(n))`. We divide each problem by half. Making it `log(n)` steps. In each step we do `O(n)` work. Same as `merge sort` complexity analysis. 36 | 37 | - **Space complexity** : `O(log(n))`. Stack space to keep on dividing in half. Same as `merge sort` complexity analysis. 38 | 39 | ## Complexity Analysis (Brute Force): 40 | 41 | **See [Java Solution](Java/BackToBackSWESolution.java)** 42 | 43 | - **Time complexity** : `O(n^2) and O(n^3)`. For each element we consider every window (subarray) that contains this element. 44 | 45 | - **Space complexity** : `O(1)`. No extra space used 46 | 47 | #### [YouTube - Back To Back SWE - detailed kadane explanation](https://www.youtube.com/watch?v=2MmGzdiKR9Y) 48 | #### [geeksforgeeks - divide-and-conquer explanation](https://www.geeksforgeeks.org/maximum-subarray-sum-using-divide-and-conquer-algorithm/) 49 | #### [YouTube - my code school - explains all variations](https://www.youtube.com/watch?v=ohHWQf1HDfU) 50 | -------------------------------------------------------------------------------- /00_Arrays/MedianMaintenance/src/Main.kt: -------------------------------------------------------------------------------- 1 | import java.util.* 2 | 3 | class MedianMaintenance { 4 | // container for items less than the median 5 | private val lesser = PriorityQueue({ a: Int, b: Int -> -1 * a.compareTo(b)}) // MAX_HEAP 6 | // container for items greater than the median 7 | private val higher = PriorityQueue() // MIN_HEAP 8 | 9 | private fun getCurrentMedian(): Int { 10 | return when { 11 | lesser.size == higher.size -> (lesser.peek() + higher.peek()) / 2 12 | lesser.size > higher.size -> lesser.peek() 13 | else -> higher.peek() 14 | } 15 | } 16 | 17 | private fun addToAppropriateHeap(n: Int) { 18 | when { 19 | lesser.size == 0 -> lesser.add(n) 20 | n < lesser.peek() -> lesser.add(n) 21 | else -> higher.add(n) 22 | } 23 | } 24 | 25 | private fun rebalanceHeaps() { 26 | if (Math.abs(lesser.size - higher.size) == 2) { 27 | val heapWithLessItems = if (lesser.size < higher.size) lesser else higher 28 | val heapWithMoreItems = if (lesser.size > higher.size) lesser else higher 29 | heapWithLessItems.add(heapWithMoreItems.poll()) 30 | } 31 | } 32 | 33 | fun getMedian(n: Int): Int { 34 | addToAppropriateHeap(n) 35 | rebalanceHeaps() 36 | return getCurrentMedian() 37 | } 38 | } 39 | 40 | fun main(args: Array) { 41 | val mm = MedianMaintenance() 42 | val stream: Array = arrayOf(5, 15, 1, 3, 2, 8, 7, 9, 10, 6, 11, 4) 43 | val expectedAnswer = arrayOf(5, 10, 5, 4, 3, 4, 5, 6, 7, 6, 7, 6) 44 | 45 | val answer = stream.map { mm.getMedian(it) }.toTypedArray() 46 | 47 | if (answer contentEquals expectedAnswer) { 48 | println("Test passed!") 49 | } else { 50 | println("Test failed!") 51 | } 52 | } -------------------------------------------------------------------------------- /00_Arrays/MedianMaintenance/src/README.md: -------------------------------------------------------------------------------- 1 | # MedianMaintenance 2 | 3 | Given that integers are read from a data stream. Find median of elements read so for in efficient way. For simplicity assume there are no duplicates. For example, let us consider the stream 5, 15, 1, 3 … 4 | 5 | ``` 6 | After reading 1st element of stream - 5 -> median - 5 7 | After reading 2nd element of stream - 5, 15 -> median - 10 8 | After reading 3rd element of stream - 5, 15, 1 -> median - 5 9 | After reading 4th element of stream - 5, 15, 1, 3 -> median - 4, so on... 10 | ``` 11 | 12 | Making it clear, when the input size is odd, we take the middle element of sorted data. If the input size is even, we pick average of middle two elements in sorted stream. 13 | 14 | Source: https://www.geeksforgeeks.org/median-of-stream-of-integers-running-integers/ 15 | 16 | ## Solution 17 | 18 | we can use a max heap on left side to represent elements that are less than effective median, and a min heap on right side to represent elements that are greater than effective median. 19 | 20 | After processing an incoming element, the number of elements in heaps differ utmost by 1 element. When both heaps contain same number of elements, we pick average of heaps root data as effective median. When the heaps are not balanced, we select effective median from the root of heap containing more elements. -------------------------------------------------------------------------------- /00_Arrays/MostFrequentInteger/README.md: -------------------------------------------------------------------------------- 1 | ## Most Frequent Integer 2 | ``` 3 | Find the most frequent integer in an array 4 | 5 | Time O(n) 6 | Space O(1) - TODO 7 | ``` -------------------------------------------------------------------------------- /00_Arrays/MostFrequentInteger/Solution.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | # time O(n) 4 | # space O(n) 5 | class Solution(object): 6 | def getMostFreqInteger(self, arr): 7 | if len(arr) is 1: 8 | return arr[0] 9 | dic = {} 10 | for i in range(len(arr)): 11 | if arr[i] in dic: 12 | dic[arr[i]] += 1 13 | else: 14 | dic[arr[i]] = 1 15 | max_count = 0 16 | max_item = '' 17 | for k, v in dic.items(): 18 | if(max_count < v): 19 | max_count = v 20 | max_item = k 21 | return max_item 22 | 23 | """ 24 | Constraint: element in array can range from 0 to k-1, k <= n 25 | """ 26 | def getMostFreqInteger_2(self, arr): 27 | if len(arr) == 0: 28 | return '' 29 | if len(arr) == 1: 30 | return arr[0] 31 | k = len(arr) 32 | return self._helper(arr, len(arr), k) 33 | 34 | def _helper(self, arr, n, k): 35 | for i in range(n): 36 | arr[ arr[i] % k] += k 37 | maxnum = arr[0] 38 | result = '' # index specifies the maximum element uptained 39 | for i in range(1, n): 40 | if arr[i] > maxnum: 41 | maxnum = arr[i] 42 | result = i 43 | return result 44 | 45 | # unittesting 46 | class TestMostFrequentInteger(unittest.TestCase): 47 | def test_few_elements(self): 48 | self.assertEqual(Solution().getMostFreqInteger([2, 1, 3, 1, 4, 4, 4]), 4) 49 | self.assertEqual(Solution().getMostFreqInteger_2([2, 1, 3, 1, 4, 4, 4]), 4) 50 | 51 | def test_one_element(self): 52 | self.assertEqual(Solution().getMostFreqInteger([1]), 1) 53 | self.assertEqual(Solution().getMostFreqInteger_2([1]), 1) 54 | 55 | def test_no_element(self): 56 | self.assertEqual(Solution().getMostFreqInteger([]), '') 57 | self.assertEqual(Solution().getMostFreqInteger_2([]), '') 58 | 59 | def main(): 60 | unittest.main() 61 | # print Solution().getMostFreqInteger([]) 62 | 63 | if __name__ == '__main__': 64 | main() -------------------------------------------------------------------------------- /00_Arrays/Permutation/Permutation.java: -------------------------------------------------------------------------------- 1 | /* 2 | Imported from 3 | http://introcs.cs.princeton.edu/java/23recursion/Permutations.java.html 4 | */ 5 | 6 | import java.util.*; 7 | import java.lang.*; 8 | import java.io.*; 9 | 10 | /* Name of the class has to be "Main" only if the class is public. */ 11 | class Permutations { 12 | 13 | // print N! permutation of the characters of the string s (in order) 14 | public static void perm1(String s) { perm1("", s); } 15 | private static void perm1(String prefix, String s) { 16 | int N = s.length(); 17 | if (N == 0) System.out.println(prefix); 18 | else { 19 | for (int i = 0; i < N; i++) 20 | perm1(prefix + s.charAt(i), s.substring(0, i) + s.substring(i+1, N)); 21 | } 22 | 23 | } 24 | 25 | // print N! permutation of the elements of array a (not in order) 26 | public static void perm2(String s) { 27 | int N = s.length(); 28 | char[] a = new char[N]; 29 | for (int i = 0; i < N; i++) 30 | a[i] = s.charAt(i); 31 | perm2(a, N); 32 | } 33 | 34 | private static void perm2(char[] a, int n) { 35 | if (n == 1) { 36 | System.out.println(a); 37 | return; 38 | } 39 | for (int i = 0; i < n; i++) { 40 | swap(a, i, n-1); 41 | perm2(a, n-1); 42 | swap(a, i, n-1); 43 | } 44 | } 45 | 46 | // swap the characters at indices i and j 47 | private static void swap(char[] a, int i, int j) { 48 | char c; 49 | c = a[i]; a[i] = a[j]; a[j] = c; 50 | } 51 | 52 | 53 | 54 | public static void main(String[] args) { 55 | int N = Integer.parseInt(args[0]); 56 | String alphabet = "abc"; 57 | String elements = alphabet.substring(0, N); 58 | perm1(elements); 59 | System.out.println(); 60 | perm2(elements); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /00_Arrays/Permutation/README.md: -------------------------------------------------------------------------------- 1 | [Explained well in SO](http://stackoverflow.com/questions/4240080/generating-all-permutations-of-a-given-string) 2 | -------------------------------------------------------------------------------- /00_Arrays/RemoveDuplicatesFromSortedArray/C++/Solution.cpp: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public: 3 | int removeDuplicates(int A[], int n) { 4 | if (n < 2) return n; 5 | int index = 0; 6 | for (int i = 1; i < n; i++) { 7 | if (A[index] != A[i]) // only if the encountering numbering is unique 8 | A[++index] = A[i]; // copy that to the unique array 9 | } 10 | return index + 1; // return the length of the unique elements array 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /00_Arrays/RemoveDuplicatesFromSortedArray/Java/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.Arrays; 2 | 3 | public class Solution { 4 | public static int removeDuplicates(int[] A) { 5 | int n = A.length; 6 | if (n < 2) return n; 7 | int index = 0; 8 | for (int i = 1; i < n; i++) { 9 | if (A[index] != A[i]) 10 | A[++index] = A[i]; 11 | } 12 | return index + 1; 13 | } 14 | public static void main(String[] args) { 15 | int[] A = { 1, 2, 2, 3, 3 }; 16 | removeDuplicates(A); 17 | System.out.println( Arrays.toString(A)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /00_Arrays/RemoveDuplicatesFromSortedArray/README.md: -------------------------------------------------------------------------------- 1 | # Remove Duplicates from Sorted Array 2 | 3 | [See in 4 | LeetCode](https://oj.leetcode.com/problems/remove-duplicates-from-sorted-array/) 5 | 6 | Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length. 7 | 8 | Do not allocate extra space for another array, you must do this in place with constant memory. 9 | 10 | For example, 11 | Given input array A = `[1,1,2]`, 12 | 13 | Your function should return length = `2`, and A is now `[1,2]`. 14 | 15 | ## Solution 16 | 17 | Using Loop invariant this can be solved. 18 | 19 | We have to get a pointer to the array, which is such that we know that the array elements till that pointer are all unique. 20 | 21 | ### Issues 22 | If the input array is {1, 2, 2, 3, 3}, the array will be changed to {1, 2, 3, 3, 3}. 23 | 24 | Since we return the length of the new array too, the answer passes the leetcode test cases. 25 | -------------------------------------------------------------------------------- /00_Arrays/SegregatePositiveAndNegativeNumbers/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | Given an array of unknown size, reverse the positive numbers (before a negative marker) in the array. Ex: [2, 3, 1, 4,-1...] would become [4, 1, 3, 2, -1...] 3 | ``` -------------------------------------------------------------------------------- /00_Arrays/SegregatePositiveAndNegativeNumbers/python/solution.py: -------------------------------------------------------------------------------- 1 | arr = [4, -1, 1, -5, 2, -6, 3] 2 | 3 | high = len(arr) - 1 4 | low = 0 5 | 6 | def swap(i, j): 7 | arr[i], arr[j] = arr[j], arr[i] 8 | 9 | index = 0 10 | while(index <= high): 11 | if arr[index] > 0: 12 | swap(index, low) 13 | low += 1 14 | index += 1 15 | 16 | print arr 17 | -------------------------------------------------------------------------------- /00_Arrays/best-time-to-buy-and-sell-stock/README.md: -------------------------------------------------------------------------------- 1 | # Best Time to Buy and Sell Stock 2 | 3 | `Easy` 4 | 5 | Say you have an array for which the ith element is the price of a given stock on day i. 6 | 7 | If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit. 8 | 9 | Note that you cannot sell a stock before you buy one. 10 | 11 | ## Example 1: 12 | ``` 13 | 14 | Input: [7,1,5,3,6,4] 15 | Output: 5 16 | Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. 17 | Not 7-1 = 6, as selling price needs to be larger than buying price. 18 | ``` 19 | 20 | ## Example 2: 21 | ``` 22 | 23 | Input: [7,6,4,3,1] 24 | Output: 0 25 | Explanation: In this case, no transaction is done, i.e. max profit = 0. 26 | ``` 27 | 28 | ## Complexity Analysis: 29 | 30 | - **Time complexity** : `O(n)`. We traverse each the list only once. 31 | 32 | - **Space complexity** : `O(1)`. The extra space is used to store 2 variables. The minimum so far and the max profit so far. 33 | -------------------------------------------------------------------------------- /00_Arrays/best-time-to-buy-and-sell-stock/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} prices 3 | * @return {number} 4 | */ 5 | var maxProfit = function(prices) { 6 | let minSoFar = Number.MAX_SAFE_INTEGER 7 | let maxProfit = 0; 8 | prices.forEach((value) => { 9 | if (value < minSoFar) { 10 | minSoFar = value 11 | } else { 12 | const profit = value - minSoFar 13 | maxProfit = Math.max(maxProfit, profit) 14 | } 15 | }) 16 | return maxProfit; 17 | }; 18 | -------------------------------------------------------------------------------- /00_Arrays/containsSum/C++/Makefile: -------------------------------------------------------------------------------- 1 | CC := gcc 2 | CFLAGS := -O0 -g -std=c99 -Wall -Wextra -Wshadow -pedantic -Werror 3 | CXXFLAGS := -O0 -g -std=c++11 -Wall -Wextra -Wshadow -pedantic -Weffc++ -Werror 4 | -------------------------------------------------------------------------------- /00_Arrays/containsSum/C++/main: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alxerg/Interview-Questions/ac05100917cdc9b486218eeb091baaac38a84639/00_Arrays/containsSum/C++/main -------------------------------------------------------------------------------- /00_Arrays/containsSum/C++/main.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | bool hasSum(int nums[], size_t size, int neededSum) { 6 | std::sort(nums, nums + size); 7 | size_t low = 0; 8 | size_t high = size-1; 9 | while(low < high) { 10 | int sum = nums[low] + nums[high]; 11 | if(neededSum == sum) return true; 12 | else if (neededSum > sum) low++; 13 | else high--; 14 | } 15 | return false; 16 | } 17 | 18 | int main(void) 19 | { 20 | int arr[] = {1, 2, 7, 2, 3, 4}; 21 | size_t n = sizeof(arr)/sizeof(arr[0]); 22 | assert( hasSum(arr, n, 5) == true ); 23 | assert( hasSum(arr, n, 50) == false ); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /00_Arrays/containsSum/README.md: -------------------------------------------------------------------------------- 1 | **Given an integer x and an unsorted array of integers, describe an algorithm to determine whether two of the numbers add up to x. (In this case, say that the interviewer hates hash tables.)** 2 | 3 | ## Solution 4 | 5 | - Good Answer : Sort the array. Then, keep track of two pointers in the array, one at the beginning and one at the end. Whenever the sum of the current two integers is less than x, move the first pointer forwards, and whenever the sum is greater than x, move the second pointer backwards. If you cannot find two numbers that add to x before one of the pointers meet, then there is no pair of integers that sum to x. This solution takes `O(nlogn)` time because we sort the numbers. 6 | 7 | - Another Good Answer : Create a binary search tree containing x minus each element in the array. Then, check whether any element of the array appears in the BST. It takes O(nlogn) time to create a binary search tree from an array, since it takes O(logn) time to insert something into a BST, and it takes O(nlogn) time to see if any element in an array is in a BST, since the lookup time for each element in the array takes O(logn). Therefore step one takes `O(nlogn)`time and step two takes `O(nlogn)` time, so our total running time is O(nlogn). 8 | -------------------------------------------------------------------------------- /00_Arrays/containsSum/Solution.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | 3 | public static boolean hasSum(int[] array, int sum) { 4 | java.util.Arrays.sort(array); 5 | int first = 0; 6 | int second = array.length - 1; 7 | while(first < second) { 8 | int gotSum = array[first] + array[second]; 9 | if (gotSum == sum) 10 | return true; 11 | else if (gotSum < sum) 12 | first++; 13 | else 14 | second--; 15 | } 16 | return false; 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /00_Arrays/coupleSum/README.md: -------------------------------------------------------------------------------- 1 | Given an array of integers, find two numbers such that they sum up to a specific target. 2 | 3 | The method `coupleSum` should return the indices of the two numbers in the array, where index1 must be less than index2. 4 | Please note that the indices are not zero based, and you can assume that each input has exactly one solution. Target linear runtime and space complexity. 5 | 6 | ## Example: 7 | 8 | ``` 9 | Input Array : {2, 3, 4, 7} 10 | Target : 7 11 | Output : {2, 3} 12 | ``` 13 | 14 | ## Complexity Analysis: 15 | 16 | - **Time complexity** : `O(n)`. We traverse the list containing *n* elements only once. Each look up in the table costs only `O(1)` time. 17 | 18 | - **Space complexity** : `O(n)`. The extra space required depends on the number of items stored in the hash table, which stores at most *n* elements. 19 | 20 | ### [Leetcode Problem](https://leetcode.com/problems/two-sum/) 21 | -------------------------------------------------------------------------------- /00_Arrays/coupleSum/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | class Solution { 3 | public static int[] coupleSum(int[] numbers, int target) { 4 | HashMap map = new HashMap<>(); 5 | 6 | for (int i=0; i < numbers.length; i++) { 7 | map.put(numbers[i], i); 8 | } 9 | 10 | for (int i=0; i < numbers.length; i++) { 11 | int num = target - numbers[i]; 12 | if (map.containsKey(num)) { 13 | int j = map.get(num); 14 | return new int[] {i+1, j+1}; 15 | } 16 | } 17 | 18 | return new int[] {-1,-1}; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /00_Arrays/coupleSum/solution.js: -------------------------------------------------------------------------------- 1 | // two pass hashmap solution 2 | const twoSum2 = function(nums, target) { 3 | const cache = {} 4 | // put a map of 5 | nums.forEach((value, index) => { 6 | cache[value] = index 7 | }) 8 | // iterate through array and check if we had the needed value in the hashmap 9 | for (let i=0; i< nums.length; i++) { 10 | const needed = target - nums[i] 11 | // initial check is to see if we dont use the same number 12 | if (needed in cache) { 13 | const j = cache[needed] 14 | if (i !== j) return [i, j] 15 | } 16 | } 17 | return [] 18 | }; 19 | 20 | // 1 pass hashmap solution 21 | var twoSum = function(nums, target) { 22 | // put a map of 23 | const cache = {} 24 | // iterate through array and check if we had the needed value in the hashmap 25 | for (let i=0; i< nums.length; i++) { 26 | const needed = target - nums[i] 27 | if (needed in cache) { 28 | const j = cache[needed] 29 | return [i, j] 30 | } 31 | cache[nums[i]] = i 32 | } 33 | return [] 34 | }; 35 | -------------------------------------------------------------------------------- /00_Arrays/find-minimum-in-rotated-sorted-array/README.md: -------------------------------------------------------------------------------- 1 | # Find Minimum in Rotated Sorted Array 2 | 3 | ![Medium difficulty](https://img.shields.io/badge/difficulty-medium-yellow) 4 | 5 | ![Binary Search](https://img.shields.io/badge/Technique-Binary_Search-blue) 6 | 7 | Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. 8 | 9 | (i.e., `[0,1,2,4,5,6,7]` might become `[4,5,6,7,0,1,2]`). 10 | 11 | Find the minimum element. 12 | 13 | You may assume no duplicate exists in the array. 14 | 15 | ## Example 1: 16 | 17 | ``` 18 | Input: [3,4,5,1,2] 19 | Output: 1 20 | ``` 21 | 22 | ## Example 2: 23 | 24 | ``` 25 | Input: [4,5,6,7,0,1,2] 26 | Output: 0 27 | ``` 28 | 29 | ## Complexity Analysis: 30 | 31 | - **Time complexity** : `O(log n)`. Same as binary search 32 | 33 | - **Space complexity** : `O(1)`. only 3 variables have been used. 34 | 35 | ### [Leetcode Problem](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array) 36 | -------------------------------------------------------------------------------- /00_Arrays/insert-interval/README.md: -------------------------------------------------------------------------------- 1 | # Insert Interval 2 | 3 | ![Difficulty-Hard](https://img.shields.io/badge/Difficulty-Hard-red) 4 | 5 | Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). 6 | 7 | You may assume that the intervals were initially sorted according to their start times. 8 | 9 | ## Example 1: 10 | 11 | ``` 12 | Input: intervals = [[1,3],[6,9]], newInterval = [2,5] 13 | Output: [[1,5],[6,9]] 14 | ``` 15 | 16 | ## Example 2: 17 | 18 | ``` 19 | Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] 20 | Output: [[1,2],[3,10],[12,16]] 21 | Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10]. 22 | ``` 23 | 24 | 25 | ## Complexity Analysis: 26 | 27 | - **Time complexity** : `O(n)`. We traverse the list containing *n* elements only once. The overlap merge opration costs `O(1)` time. 28 | 29 | - **Space complexity** : `O(n)`. The extra space is at worst case *n + 1* array space. Where there is no overlap and we return the original array and the inserted element together 30 | 31 | ### [Leetcode Problem](https://leetcode.com/problems/insert-interval/) 32 | -------------------------------------------------------------------------------- /00_Arrays/insert-interval/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} intervals 3 | * @param {number[]} newInterval 4 | * @return {number[][]} 5 | */ 6 | 7 | var insert = function(intervals, newInterval) { 8 | const result = [] 9 | let i = 0 10 | // add all the intervals ending before merging-interval starts 11 | while (i < intervals.length && newInterval[0] > intervals[i][1]) { 12 | result.push(intervals[i]) 13 | i++ 14 | } 15 | let startRes = newInterval[0] 16 | let endRes = newInterval[1] 17 | // merge all overlapping intervals to one considering merging-interval 18 | while (i < intervals.length && newInterval[1] >= intervals[i][0]) { 19 | startRes = Math.min(startRes, intervals[i][0]) 20 | endRes = Math.max(endRes, intervals[i][1]) 21 | i++ 22 | } 23 | // merge the newly created merging-interval 24 | result.push([startRes, endRes]) 25 | // push the rest 26 | while (i < intervals.length) { 27 | result.push(intervals[i]) 28 | i++ 29 | } 30 | return result 31 | }; 32 | -------------------------------------------------------------------------------- /00_Arrays/kLargestNumbers/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | Write an efficient program for printing k largest elements in an array. Elements in array can be in any order. 3 | ``` -------------------------------------------------------------------------------- /00_Arrays/kLargestNumbers/Solution.java: -------------------------------------------------------------------------------- 1 | public class MaxHeap { 2 | int[] arr; 3 | int N; 4 | 5 | public MaxHeap(int capacity) { 6 | arr = new int[capacity + 1]; 7 | N = 0; 8 | } 9 | 10 | public void insert(int value) { 11 | arr[++N] = value; 12 | swim(N); 13 | } 14 | 15 | public int deleteMax() { 16 | swap(N, 1, arr); 17 | 18 | int max = arr[N]; 19 | arr[N] = 0; 20 | N--; 21 | sink(1); 22 | return max; 23 | } 24 | 25 | public boolean isEmpty() { 26 | return N == 0; 27 | } 28 | 29 | private int max(int a, int b) { 30 | return (a>b) ?a : b; 31 | } 32 | 33 | /* 34 | * swim max to top 35 | */ 36 | private void swim(int index) { 37 | while(arr[index] > arr[index/2] && index != 0 && index/2 != 0) { 38 | swap(index, index/2, arr); 39 | index = index/2; 40 | } 41 | } 42 | 43 | /* 44 | * Sink the element from top to bottom 45 | */ 46 | private void sink(int index) { 47 | while(index < N) { 48 | int childIndex = 2 * index; 49 | int maxChildIndex = (arr[childIndex] > arr[childIndex + 1])?childIndex :(childIndex + 1); 50 | if(arr[index] > arr[maxChildIndex]) { 51 | break; 52 | } 53 | //System.out.println("max child index :" + maxChildIndex); 54 | swap(index, maxChildIndex, arr); 55 | index = maxChildIndex; 56 | } 57 | } 58 | 59 | /* 60 | * swaps entries between two index in arr 61 | */ 62 | private void swap(int index1, int index2, int[] arr) { 63 | int temp = arr[index1]; 64 | arr[index1] = arr[index2]; 65 | arr[index2] = temp; 66 | } 67 | 68 | /* 69 | * diplays elements of queue 70 | */ 71 | public void display() { 72 | for(int i = 1; i <= N; i++) { 73 | System.out.print(arr[i] + " "); 74 | } 75 | System.out.println(); 76 | } 77 | 78 | public static void main(String[] args) { 79 | MaxHeap h = new MaxHeap(20); 80 | int[] arr = {1, 23, 12, 9, 30, 2, 50}; 81 | for(int i = 0; i < arr.length; i++) { 82 | h.insert(arr[i]); 83 | } 84 | System.out.println("first highest element is " + h.deleteMax()); 85 | System.out.println("second highest element is " + h.deleteMax()); 86 | System.out.println("third highest element is " + h.deleteMax()); 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /00_Arrays/maximum-product-subarray/README.md: -------------------------------------------------------------------------------- 1 | # Maximum Product Subarray 2 | 3 | ![Medium difficulty](https://img.shields.io/badge/difficulty-medium-yellow) 4 | 5 | ![Dynamic Programming Technique](https://img.shields.io/badge/Technique-Dynamic_Programming-blue) 6 | 7 | Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which has the largest product. 8 | 9 | ## Example 1: 10 | 11 | ``` 12 | Input: [2,3,-2,4] 13 | Output: 6 14 | Explanation: [2,3] has the largest product 6. 15 | ``` 16 | 17 | ## Example 2: 18 | 19 | ``` 20 | Input: [-2,0,-1] 21 | Output: 0 22 | Explanation: The result cannot be 2, because [-2,-1] is not a subarray. 23 | ``` 24 | 25 | ## Complexity Analysis: 26 | 27 | - **Time complexity** : `O(n) - linear`. We sweep the array once. 28 | 29 | - **Space complexity** : `O(1)`. We use 3 extra variables for global max, and the previous subarray max/min sums. -------------------------------------------------------------------------------- /00_Arrays/maximum-product-subarray/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number} 4 | */ 5 | var maxProduct = function(nums) { 6 | // borrowing the same idea from kadane's algorithm for max contigous subarray sum 7 | let maxProd = null 8 | // we have two variables which keep track of subarray sum (max or min) which includes the previous element 9 | let prevSubArrayMaxProd = null 10 | // we keep track of minimum as well, because when multiplying with negative numbers multpying with min will give the maximum 11 | let prevSubArrayMinProd = null 12 | nums.forEach(num => { 13 | const currSubArrayMaxProd = prevSubArrayMaxProd !== null && prevSubArrayMinProd !== null ? Math.max(num, prevSubArrayMaxProd * num, prevSubArrayMinProd * num) : num 14 | const currSubArrayMinProd = prevSubArrayMaxProd !== null && prevSubArrayMinProd !== null ? Math.min(num, prevSubArrayMaxProd * num, prevSubArrayMinProd * num) : num 15 | // the max containing this element is a candiate for our global max 16 | maxProd = maxProd !== null ? Math.max(maxProd, currSubArrayMaxProd) : currSubArrayMaxProd 17 | prevSubArrayMaxProd = currSubArrayMaxProd 18 | prevSubArrayMinProd = currSubArrayMinProd 19 | }) 20 | return maxProd 21 | }; -------------------------------------------------------------------------------- /00_Arrays/merge-intervals/README.md: -------------------------------------------------------------------------------- 1 | # Merge Intervals 2 | 3 | ![Medium difficulty](https://img.shields.io/badge/difficulty-medium-yellow) 4 | 5 | ## Example 1: 6 | 7 | ``` 8 | Input: intervals = [[1,3],[2,6],[8,10],[15,18]] 9 | Output: [[1,6],[8,10],[15,18]] 10 | Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6]. 11 | ``` 12 | 13 | ## Example 2: 14 | 15 | ``` 16 | Input: intervals = [[1,4],[4,5]] 17 | Output: [[1,5]] 18 | Explanation: Intervals [1,4] and [4,5] are considered overlapping. 19 | ``` 20 | 21 | ## Constraints: 22 | 23 | ``` 24 | intervals[i][0] <= intervals[i][1] 25 | ``` 26 | 27 | ## Complexity Analysis: 28 | 29 | - **Time complexity** : `O(n * log(n))`. Other than the `sort` invocation, we do a simple linear scan of the list, so the runtime is dominated by the `O(n * log(n))` complexity of sorting. 30 | 31 | - **Space complexity** : `O(1) or O(n)`. If we can sort intervals in place, we do not need more than constant additional space. Otherwise, we must allocate linear space to store a copy of intervals and sort that. The space for answer array is not counted. If counted, it is O(n). 32 | 33 | ### [Leetcode Problem](https://leetcode.com/problems/merge-intervals/) 34 | -------------------------------------------------------------------------------- /00_Arrays/merge-intervals/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} intervals 3 | * @return {number[][]} 4 | */ 5 | var merge = function (intervals) { 6 | const ans = []; 7 | if (intervals.length === 0) return ans; 8 | intervals.sort((a, b) => a[0] - b[0]); 9 | let min = intervals[0][0]; 10 | let max = intervals[0][1]; 11 | for (let i = 1; i < intervals.length; i++) { 12 | if (intervals[i][0] > max) { 13 | ans.push([min, max]); 14 | min = intervals[i][0]; 15 | max = intervals[i][1]; 16 | } else { 17 | min = Math.min(intervals[i][0], min); 18 | max = Math.max(intervals[i][1], max); 19 | } 20 | } 21 | ans.push([min, max]); 22 | return ans; 23 | }; 24 | 25 | function test(input, output) { 26 | const answer = merge(input); 27 | const testSuccess = JSON.stringify(answer) === JSON.stringify(output); 28 | if (testSuccess) { 29 | console.log("✅ PASS: ", input, " === ", output); 30 | } else { 31 | console.log( 32 | "❌ FAIL - GOT: ", 33 | answer, 34 | "EXPECTED: ", 35 | output, 36 | "INPUT: ", 37 | input 38 | ); 39 | } 40 | } 41 | 42 | // case 1 43 | test( 44 | [ 45 | [1, 3], 46 | [2, 6], 47 | [8, 10], 48 | [15, 18], 49 | ], 50 | [ 51 | [1, 6], 52 | [8, 10], 53 | [15, 18], 54 | ] 55 | ); 56 | 57 | // case 2 58 | test( 59 | [ 60 | [1, 4], 61 | [4, 5], 62 | ], 63 | [[1, 5]] 64 | ); 65 | 66 | // case 3 67 | test( 68 | [ 69 | [1, 4], 70 | [0, 0], 71 | ], 72 | [ 73 | [0, 0], 74 | [1, 4], 75 | ] 76 | ); 77 | -------------------------------------------------------------------------------- /00_Arrays/product-of-array-except-self/README.md: -------------------------------------------------------------------------------- 1 | # Product of Array Except Self 2 | 3 | ![Medium difficulty](https://img.shields.io/badge/difficulty-medium-yellow) 4 | 5 | Given an array nums of `n` integers where `n > 1`, return an array output such that `output[i]` is equal to the product of all the elements of nums except nums[i]. 6 | 7 | ## Example: 8 | 9 | ``` 10 | Input: [1,2,3,4] 11 | Output: [24,12,8,6] 12 | ``` 13 | 14 | **Constraint:** It's guaranteed that the product of the elements of any prefix or suffix of the array (including the whole array) fits in a 32 bit integer. 15 | 16 | **Note:** Please solve it without division and in O(n). 17 | 18 | ### Follow up: 19 | 20 | Could you solve it with constant space complexity? (*The output array does not count as extra space for the purpose of space complexity analysis.*) 21 | 22 | 23 | ## Complexity Analysis (L & R array + answer array solution): 24 | 25 | - **Time complexity** : `O(n)`. *n* represents the number of elements in the input array. We use one iteration to construct the array L, one to construct the array R and one last to construct the answer array using L and R. 26 | 27 | - **Space complexity** : `O(n)`. O(n) used up by the two intermediate arrays that we constructed to keep track of product of elements to the left and right. 28 | 29 | ## Complexity Analysis (answer array only solution): 30 | 31 | - **Time complexity** : `O(n)`. *n* represents the number of elements in the input array. We use one iteration to initialise the answer array with left side products, and one more iteration to update the answer array with the right side product multiplication. 32 | 33 | - **Space complexity** : `O(1)`. since don't use any additional array for our computations. The problem statement mentions that using the answer array doesn't add to the space complexity. 34 | 35 | ### [Leetcode Problem](https://leetcode.com/problems/product-of-array-except-self) 36 | -------------------------------------------------------------------------------- /00_Arrays/product-of-array-except-self/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[]} nums 3 | * @return {number[]} 4 | */ 5 | var productExceptSelf = function (nums) { 6 | const L = []; 7 | const R = []; 8 | 9 | // L[i] contains the product of all the elements to the left 10 | // Note: for the element at index '0', there are no elements to the left, 11 | // so L[0] would be 1 12 | L[0] = 1; 13 | for (let i = 1; i < nums.length; i++) { 14 | // L[i - 1] already contains the product of elements to the left of 'i - 1' 15 | // Simply multiplying it with nums[i - 1] would give the product of all 16 | // elements to the left of index 'i' 17 | L[i] = nums[i - 1] * L[i - 1]; 18 | } 19 | 20 | // R[i] contains the product of all the elements to the right 21 | // Note: for the element at index 'length - 1', there are no elements to the right, 22 | // so R[length - 1] would be 1 23 | R[nums.length - 1] = 1; 24 | // go reverse, start from one element before the last one 25 | for (let i = nums.length - 2; i >= 0; i--) { 26 | // R[i + 1] already contains the product of elements to the right of 'i + 1' 27 | // Simply multiplying it with nums[i + 1] would give the product of all 28 | // elements to the right of index 'i' 29 | R[i] = nums[i + 1] * R[i + 1]; 30 | } 31 | 32 | return nums.map((_, index) => L[index] * R[index]); 33 | }; 34 | 35 | // O(1) space solution (output array does not count to space complexity) 36 | var productExceptSelf2 = function (nums) { 37 | const ans = []; 38 | 39 | // initialise with left 40 | ans[0] = 1; 41 | for (let i = 1; i < nums.length; i++) { 42 | ans[i] = nums[i - 1] * ans[i - 1]; 43 | } 44 | 45 | // R contains the product of all the elements to the right 46 | // Note: for the element at index 'length - 1', there are no elements to the right, 47 | // so the R would be 1 48 | let R = 1; 49 | // go reverse, start from one element before the last one 50 | for (let i = nums.length - 1; i >= 0; i--) { 51 | const left = ans[i]; 52 | ans[i] = left * R 53 | R = R * nums[i] 54 | } 55 | 56 | return ans; 57 | }; 58 | 59 | function test(input, output) { 60 | const answer = productExceptSelf2(input); 61 | const testSuccess = JSON.stringify(answer) === JSON.stringify(output); 62 | if (testSuccess) { 63 | console.log("PASS: ", input, " === ", output); 64 | } else { 65 | console.log("FAIL - GOT: ", answer, "EXPECTED: ", output); 66 | } 67 | } 68 | 69 | test([1, 2, 3, 4], [24, 12, 8, 6]); 70 | -------------------------------------------------------------------------------- /00_Arrays/rotate-image/README.md: -------------------------------------------------------------------------------- 1 | # Rotate Image 2 | 3 | ![Difficulty-Medium](https://img.shields.io/badge/Difficulty-Medium-yellow) 4 | 5 | You are given an `n x n` 2D matrix representing an image. 6 | 7 | Rotate the image by 90 degrees (clockwise). 8 | 9 | ## Note: 10 | 11 | You have to rotate the image `in-place`, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation. 12 | 13 | ## Example 1: 14 | 15 | ``` 16 | Given input matrix = 17 | [ 18 | [1,2,3], 19 | [4,5,6], 20 | [7,8,9] 21 | ], 22 | 23 | rotate the input matrix in-place such that it becomes: 24 | [ 25 | [7,4,1], 26 | [8,5,2], 27 | [9,6,3] 28 | ] 29 | ``` 30 | 31 | ## Example 2: 32 | 33 | ``` 34 | Given input matrix = 35 | [ 36 | [ 5, 1, 9,11], 37 | [ 2, 4, 8,10], 38 | [13, 3, 6, 7], 39 | [15,14,12,16] 40 | ], 41 | 42 | rotate the input matrix in-place such that it becomes: 43 | [ 44 | [15,13, 2, 5], 45 | [14, 3, 4, 1], 46 | [12, 6, 8, 9], 47 | [16, 7,10,11] 48 | ] 49 | ``` 50 | 51 | ## Complexity Analysis: 52 | 53 | - **Time complexity** : `O(n * n) - linear`. We visit all the items in the 2D matrix once. 54 | 55 | - **Space complexity** : `O(1)`. It is done `in-place`. 56 | 57 | ### [LeetCode problem](https://leetcode.com/problems/rotate-image/) 58 | ### [YouTube - My Programming Sandbox](https://www.youtube.com/watch?v=Jtu6dJ0Cb94) 59 | ### [YouTube - Gayle Laakmann McDowell](https://www.youtube.com/watch?v=aClxtDcdpsQ) 60 | 61 | ## Explanation 62 | 63 | - We traverse the 2D matrix layer by layer. 64 | - Start from all four corners of the layer and then move them one by one. And swap them appropriately. 65 | 66 | > The comments in the code have a good explanation about how we sweep layer by layer 67 | -------------------------------------------------------------------------------- /00_Arrays/rotate-image/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} matrix 3 | * @return {void} Do not return anything, modify matrix in-place instead. 4 | */ 5 | 6 | /* 7 | layer 0, start 8 | A .... B 9 | ........ 10 | ........ 11 | ........ 12 | D .... C 13 | 14 | layer 1, start 15 | ......... 16 | ..A...B.. 17 | ......... 18 | ..D...C.. 19 | ......... 20 | 21 | on each iteration inside a layer 22 | * A moves right 23 | * B moves down 24 | * C moves left 25 | * D moves up 26 | */ 27 | 28 | var rotate = function(matrix) { 29 | // last_index_of_level (row or column) 30 | let last = matrix.length - 1 31 | for (let layer = 0; layer < matrix.length / 2; layer++) { 32 | for(let i=layer; i < last; i++) { 33 | // swap A -> B 34 | // swap matrix[layer][i] and matrix[i][last] 35 | let t = matrix[layer][i] 36 | matrix[layer][i] = matrix[i][last] 37 | matrix[i][last] = t 38 | // swap A -> C 39 | // swap matrix[layer][i] and matrix[last][last - 0,1..] 40 | t = matrix[layer][i] 41 | matrix[layer][i] = matrix[last][last - (i - layer)] 42 | matrix[last][last - (i - layer)] = t 43 | // swap A -> D 44 | // swap matrix[layer][i] and matrix[last - 0,1..][layer] 45 | t = matrix[layer][i] 46 | matrix[layer][i] = matrix[last - (i - layer)][layer] 47 | matrix[last - (i - layer)][layer] = t 48 | } 49 | // for every level increase, the last index goes down by one 50 | last-- 51 | } 52 | }; 53 | -------------------------------------------------------------------------------- /00_Arrays/set-matrix-zeroes/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Set Matrix Zeroes 3 | 4 | ![Medium difficulty](https://img.shields.io/badge/Difficulty-Medium-yellow) 5 | 6 | Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place. 7 | 8 | ## Example 1: 9 | 10 | ``` 11 | Input: 12 | [ 13 | [1,1,1], 14 | [1,0,1], 15 | [1,1,1] 16 | ] 17 | Output: 18 | [ 19 | [1,0,1], 20 | [0,0,0], 21 | [1,0,1] 22 | ] 23 | ``` 24 | 25 | ## Example 2: 26 | 27 | ``` 28 | Input: 29 | [ 30 | [0,1,2,0], 31 | [3,4,5,2], 32 | [1,3,1,5] 33 | ] 34 | Output: 35 | [ 36 | [0,0,0,0], 37 | [0,4,5,0], 38 | [0,3,1,0] 39 | ] 40 | ``` 41 | 42 | ## Follow up: 43 | 44 | * A straight forward solution using O(mn) space is probably a bad idea. 45 | * A simple improvement uses O(m + n) space, but still not the best solution. 46 | * Could you devise a constant space solution? 47 | 48 | ## Complexity Analysis: 49 | 50 | - **Time complexity** : `O(m * n)`. Where `m` and `n` are the number of rows and columns respectively. Comparision operation costs `O(1)` time and we traverse the whole matrix once. 51 | 52 | - **Space complexity** : `O(1)`. We only use two extra boolean variables in the solution. Everything else is done `in-place`. 53 | 54 | ### [LeetCode problem](https://leetcode.com/problems/set-matrix-zeroes/) 55 | ### [YouTube explanation](https://www.youtube.com/watch?v=6_KMkeh5kEc) 56 | 57 | -------------------------------------------------------------------------------- /00_Arrays/set-matrix-zeroes/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {number[][]} matrix 3 | * @return {void} Do not return anything, modify matrix in-place instead. 4 | */ 5 | var setZeroes = function(matrix) { 6 | const H = matrix.length 7 | const W = matrix[0] ? matrix[0].length : 0 8 | 9 | // find if the first row needs to be filled with zeros 10 | let first_row_zero = false 11 | if (H > 0) { 12 | for (let c = 0; c < W; c++) { 13 | if (matrix[0][c] === 0) { 14 | first_row_zero = true 15 | } 16 | } 17 | } 18 | 19 | // use first row as a flag to denote if columns need to be filled with zeros 20 | // start with r as 1 because for first row we dont need to see if column needs to be filled we would have it already 21 | for (let r = 1; r < H; r++) { 22 | for (let c = 0; c < W; c++) { 23 | if (matrix[r][c] === 0) { 24 | matrix[0][c] = 0 // fill the flag to denote that the column should be filled with zeroes 25 | } 26 | } 27 | } 28 | 29 | // find which cells need to be zeroed 30 | // first row is a flag, so neglect it and start from next 31 | for (let r = 1; r < H; r++) { 32 | // flag to see if the whole row needs to be zeroed 33 | let row_contains_zero = false 34 | for (let c = 0; c < W; c++) { 35 | if (matrix[r][c] === 0) { 36 | row_contains_zero = true 37 | } 38 | } 39 | // use the first row flag to see if column needs to be filled 40 | // use the row_contains_zero boolean variable to see if row needs to be filled with zeroes 41 | for (let c = 0; c < W; c++) { 42 | if (row_contains_zero || matrix[0][c] === 0) { 43 | matrix[r][c] = 0 44 | } 45 | } 46 | } 47 | 48 | // now see if first row needs to be filled with zeroes 49 | if (first_row_zero) { 50 | for (let c = 0; c < W; c++) { 51 | matrix[0][c] = 0 52 | } 53 | } 54 | 55 | }; 56 | -------------------------------------------------------------------------------- /00_Arrays/spiralOrderMatrix/Readme.md: -------------------------------------------------------------------------------- 1 | ## Spiral order Matrix 2 | 3 | Given a matrix of m * n elements (m rows, n columns), return all elements of the matrix in spiral order. 4 | 5 | Example: 6 | 7 | Given the following matrix: 8 | ``` 9 | [ 10 | [ 1, 2, 3 ], 11 | [ 4, 5, 6 ], 12 | [ 7, 8, 9 ] 13 | ] 14 | ``` 15 | You should return 16 | ``` 17 | [1, 2, 3, 6, 9, 8, 7, 4, 5] 18 | ``` 19 | -------------------------------------------------------------------------------- /00_Arrays/spiralOrderMatrix/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | public ArrayList spiralOrder(final List> a) { 3 | ArrayList result = new ArrayList(); 4 | // Populate result; 5 | int m = a.size(); 6 | int n = a.get(0).size(); 7 | int t = 0, b = m-1, l = 0, r = n-1; 8 | int dir = 0; // will be 0-left, 1=down, 2-right, 3-up; 9 | while(t <= b && l <= r) { 10 | if(dir == 0) { // right 11 | for(int i = l; i <= r; i++) { // traverse till end and change direction mark row as done 12 | // System.out.println(a.get(t).get(i)); 13 | result.add(a.get(t).get(i)); 14 | } 15 | t++; 16 | dir = 1; 17 | } 18 | if(t > b) break; // break while loop when the t > b condition breaks 19 | if(dir == 1) { //down 20 | for(int j = t; j <= b; j++) { 21 | // System.out.println(a.get(j).get(r)); 22 | result.add(a.get(j).get(r)); 23 | } 24 | // change direction and mark the column as done 25 | r--; 26 | dir = 2; 27 | } 28 | if(l > r) break; // break while loop when the l > r condition breaks 29 | if(dir == 2) { //left 30 | for(int i = r; i >= l; i--) { 31 | // System.out.println(a.get(b).get(i)); 32 | result.add(a.get(b).get(i)); 33 | } 34 | b--; 35 | dir = 3; 36 | } 37 | if(t > b) break; 38 | if(dir == 3) { // top 39 | for(int j = b; j >= t; j--) { 40 | // System.out.println(a.get(j).get(l)); 41 | result.add(a.get(j).get(l)); 42 | } 43 | l++; 44 | dir = 0; 45 | } 46 | if(l > r) break; 47 | } 48 | 49 | return result; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /00_Arrays/transposeMatrix/README.md: -------------------------------------------------------------------------------- 1 | # Transpose Matrix 2 | 3 | ![Difficulty-Easy](https://img.shields.io/badge/Difficulty-Easy-green) 4 | 5 | Given a matrix A, return the transpose of A. 6 | 7 | The transpose of a matrix is the matrix flipped over it's main diagonal, switching the row and column indices of the matrix. 8 | 9 | ## Example 1: 10 | 11 | ``` 12 | Input: [[1,2,3],[4,5,6],[7,8,9]] 13 | Output: [[1,4,7],[2,5,8],[3,6,9]] 14 | ``` 15 | 16 | ## Example 2: 17 | 18 | ``` 19 | Input: [[1,2,3],[4,5,6]] 20 | Output: [[1,4],[2,5],[3,6]] 21 | ``` 22 | 23 | ## Complexity Analysis: 24 | 25 | - **Time complexity** : `O(n * n) - linear`. We visit all the items in the 2D matrix once. 26 | 27 | - **Space complexity** : `O(n * n)`. We create a new 2D array with the same number of elements as the input. 28 | 29 | > Note: for a n x n array, we can do the same solution in-place. So the space-complexity for that is O(1) 30 | 31 | ### [LeetCode problem](https://leetcode.com/problems/transpose-matrix) 32 | ### [Youtube Explanation](https://www.youtube.com/watch?v=VDw9y6nX_ss) 33 | 34 | ![Example](https://assets.leetcode.com/uploads/2019/10/20/hint_transpose.png) -------------------------------------------------------------------------------- /00_Arrays/transposeMatrix/solution.js: -------------------------------------------------------------------------------- 1 | var transpose = function(A) { 2 | const H = A.length 3 | const W = A[0] ? A[0].length : 0 4 | // A => H x W 5 | // Result => W x H (initially filled with 0's) 6 | const result = Array(W).fill(0).map(x=>Array(H).fill(0)); 7 | for (let c = 0; c < W; c++) { 8 | for (let r = 0; r < H; r++) { 9 | // flip columns and rows 10 | result[c][r] = A[r][c] 11 | } 12 | } 13 | return result 14 | }; -------------------------------------------------------------------------------- /01_Strings/FindTheFirstNonRepetitiveChar/README.md: -------------------------------------------------------------------------------- 1 | #### First Non Repetitive character in String 2 | 3 | 4 | Leetcode: [First Unique Character in a String](https://leetcode.com/problems/first-unique-character-in-a-string/) 5 | 6 | 7 | Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1. 8 | 9 | ``` 10 | Examples: 11 | 12 | s = "leetcode" 13 | return 0. 14 | 15 | s = "loveleetcode", 16 | return 2. 17 | ``` 18 | 19 | **Note:** You may assume the string contain only lowercase letters. 20 | -------------------------------------------------------------------------------- /01_Strings/FindTheFirstNonRepetitiveChar/Solution.kt: -------------------------------------------------------------------------------- 1 | class Solution { 2 | fun firstUniqChar(s: String): Int { 3 | // there are only lowercase letters so make an array of size 26 for a-z 4 | val charCount = IntArray(26) 5 | // 'a' - 'a' = 0 ... 'z' - 'a' = 25 6 | // so we can make use of that to get the index of the character in the array 7 | // now populate the array with the count 8 | for (i in 0 until s.length) 9 | charCount[s[i] - 'a']++ 10 | 11 | // iterate the string again now 12 | // check for count in the array, if the count is exacly 1 then it is non-repeating 13 | for (i in 0 until s.length) 14 | if (charCount[s[i] - 'a'] == 1) 15 | return i 16 | return -1 17 | } 18 | 19 | fun firstUniqCharWithMap(s: String): Int { 20 | // the map holds the character as its key 21 | // the value is the amount of times that the character has occured in the string 22 | val map = HashMap() 23 | // itreate over the string and build the map 24 | for (index in s.indices) { 25 | val character = s[index] 26 | val count = map.get(character) ?: 0 27 | map.put(character, count + 1) 28 | } 29 | // iterate over the string 30 | for (index in s.indices) { 31 | val character = s[index] 32 | val count = map.get(character)!! 33 | // if the count was exactly 1, then it was non repeating/unique 34 | if (count == 1) return index 35 | } 36 | return -1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /01_Strings/FindTheFirstNonRepetitiveChar/Solution.py: -------------------------------------------------------------------------------- 1 | def first_char(str): 2 | char_dict = {} 3 | for i in range(len(str)): 4 | if str[i] in char_dict: 5 | char_dict[str[i]] += 1 6 | else: 7 | char_dict[str[i]] = 1 8 | for i in range(len(str)): 9 | if char_dict[str[i]] == 1: #found the char with 1 occurance 10 | return str[i] 11 | return '' 12 | 13 | # function to test expected and actual output 14 | def test(got, expected): 15 | if got == expected: 16 | prefix = ' OK ' 17 | else: 18 | prefix = ' X ' 19 | print '%s got: %s expected: %s' % (prefix, repr(got), repr(expected)) 20 | 21 | # starting function 22 | def main(): 23 | print 'testing first non repetitive character' 24 | assert first_char('abcab') == 'c' 25 | assert first_char('aaaaaa') == '' 26 | assert first_char('asdfghjklasdfghjsdfhjkgshaj') == 'l' 27 | print 'All is well :)' 28 | 29 | if __name__ == '__main__': 30 | main() -------------------------------------------------------------------------------- /01_Strings/Permutation/README.md: -------------------------------------------------------------------------------- 1 | ## Permutations of String 2 | ``` 3 | Given a string, Print all the permutations of the string 4 | ``` -------------------------------------------------------------------------------- /01_Strings/Permutation/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | import java.lang.*; 3 | import java.io.*; 4 | 5 | 6 | class Solution 7 | { 8 | private static void permute(String cur, String pend) { 9 | if(pend.length() == 0) { 10 | System.out.println(cur); 11 | return; 12 | } 13 | for(int i = 0; i < pend.length(); i++) { 14 | String c = cur + pend.substring(i, i+1); 15 | String p = pend.substring(0,i) + pend.substring(i+1, pend.length()); 16 | permute(c,p); 17 | } 18 | 19 | } 20 | public static void main (String[] args) throws java.lang.Exception 21 | { 22 | String str = "ABC"; 23 | permute("", str); // prints all permutations 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /01_Strings/Permutation/Solution.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def permute(self, nums): 3 | result = [] 4 | used = [False] * len(nums) 5 | self.permuteRec(result, used, [], nums) 6 | return result 7 | 8 | """ 9 | result is array which is place holder all the permutations 10 | used is boolean array for indication which char is used till now 11 | cur holds the cur characters in the permutation 12 | nums is the initial array given by the use 13 | """ 14 | 15 | def permuteRec(self, result, used, cur, nums): 16 | # if cur contains all nums then add to result 17 | if len(cur) == len(nums): 18 | result.append(cur + []) 19 | return 20 | for i in range(len(nums)): 21 | if not used[i]: 22 | used[i] = True 23 | cur.append(nums[i]) 24 | self.permuteRec(result, used, cur, nums) 25 | #back track 26 | # if we dont revert these things back we wont be going into the next recution 27 | cur.pop() 28 | used[i] = False 29 | 30 | #/* 31 | # Imported from 32 | # http://introcs.cs.princeton.edu/java/23recursion/Permutations.java.html 33 | 34 | class Permutation(object): 35 | # prefix hold the formed permutation string 36 | # str is the input string 37 | def run(self, str): 38 | result = [] 39 | self.permute("", str, result) 40 | return result 41 | 42 | def permute(self, prefix, str, result): 43 | n = len(str) 44 | if n == 0: 45 | # print prefix 46 | result.append(prefix) 47 | for i in range(n): 48 | # for each recurtion remove the corresponding char 49 | self.permute(prefix + str[i], str[0:i] + str[i+1:n], result) 50 | 51 | # Permutations already exist in itertools library 52 | # from itertools import permutations 53 | 54 | def main(): 55 | pgm = Solution() 56 | p = pgm.permute 57 | print p(list('ABC')) 58 | 59 | print 'testing with permutation class' 60 | pgm2 = Permutation() 61 | # pgm2.permute("", "ABC") 62 | print pgm2.run("ABC") 63 | 64 | 65 | if __name__ == '__main__': 66 | main() -------------------------------------------------------------------------------- /01_Strings/README.md: -------------------------------------------------------------------------------- 1 | # Strings 2 | 3 | 1. Implement an algorithm to determine if a string has all unique characters. What if you cannot use addtional data structures? 4 | 2. How to reverse a string in c? 5 | 3. Given two strings, write a method to decide if one is a permutation of the other? **[isAnagram](isAnagram)** 6 | 4. Write a method to replace all spaces in a string with '%20'. 7 | * You may assume that the string has sufficient space at the end of the string to hold the additional characters, 8 | * and that you are given the "true" length of the string. (Note: if implementing in java, please use a character array so that you can perform this operation in place.) 9 | 5. Implement a method to perform basic string compression using the counts of repeated characters. For example, the string `aabcccccaaa` would become `a2b1c5a3`. 10 | * If the "compressed" string would not become smaller than the original string, your method should return the original string. 11 | 6. Assume you have a method `isSubstring` which checks if one word is a substring of another. Given two strings, s1 and s2, write code to check if s2 is a rotation of s1 using only one call to isSubstring (e.g., "waterbottle" is a rotation of "erbottlewat"). 12 | 7. Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1. **[FindTheFirstNonRepetitiveChar](FindTheFirstNonRepetitiveChar)** 13 | 8. Given a string, find the length of the longest substring without repeating characters. **[longest-substring-without-repeating-characters](longest-substring-without-repeating-characters)** 14 | 15 | > Questions 1-6 have been taken from [Cracking the Coding Interview](http://www.amazon.com/Cracking-Coding-Interview-6th-Edition/dp/0984782850) 16 | -------------------------------------------------------------------------------- /01_Strings/StringReverseInPlace/StringReverseInPlace.java: -------------------------------------------------------------------------------- 1 | /* 2 | Reverse the string without having any additional data structure 3 | 4 | PS: here I did use a single character as a temp(which is the only additional data structure) 5 | @author: prakashn27 6 | */ 7 | 8 | import java.util.*; 9 | import java.lang.*; 10 | import java.io.*; 11 | 12 | class StringReverseInPlace 13 | { 14 | char[] reverse(char[] name, int len) { 15 | // int l = name.length(); 16 | int j,i = 0; 17 | char temp; 18 | for(i = 0, j = len; i < j; i++,j--) { 19 | temp = name[i]; //swapping 20 | name[i] = name[j]; 21 | name[j] = temp; 22 | } 23 | /* To return a string use 24 | return new String(name); */ 25 | return name; 26 | } 27 | 28 | public static void main (String[] args) throws java.lang.Exception 29 | { 30 | StringReverseInPlace pgm = new StringReverseInPlace(); 31 | String name = "prakash"; 32 | System.out.println(pgm.reverse(name.toCharArray(), 33 | name.length()-1));//sending the length-1 as array index is one less than the total length 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /01_Strings/checkForUniqueCharacters/README.md: -------------------------------------------------------------------------------- 1 | ## Check for Unique Characters in String 2 | ``` 3 | Check if a String is composed of all unique characters 4 | ``` -------------------------------------------------------------------------------- /01_Strings/checkForUniqueCharacters/Soultion.py: -------------------------------------------------------------------------------- 1 | 2 | def isUnique(str): 3 | char_set = set() #set to strore all the characters 4 | if(len(str) == 1 or len(str) == 0): 5 | return True 6 | for i in range(len(str)): 7 | if str[i] in char_set: #if the char is already in set not unique 8 | return False 9 | else: 10 | char_set.add(str[i]) #add the element into the set 11 | return True 12 | 13 | 14 | def main(): 15 | print "checking for unique charaters in string" 16 | assert isUnique("asdf") == True 17 | assert isUnique("ass") == False 18 | assert isUnique('') == True 19 | assert isUnique('asdfghjklqwertyuiop;') == True 20 | print "all is well :)" 21 | 22 | if __name__ == '__main__': 23 | main() -------------------------------------------------------------------------------- /01_Strings/isAnagram/README.md: -------------------------------------------------------------------------------- 1 | ## Is Anagram 2 | 3 | ![Easy difficulty](https://img.shields.io/badge/Difficulty-Easy-green) 4 | 5 | Given two strings s and t , write a function to determine if t is an anagram of s. 6 | 7 | > An anagram is a result of rearranging the letters of a word to produce a new word. 8 | 9 | ## Example 1: 10 | 11 | ``` 12 | Input: s = "anagram", t = "nagaram" 13 | Output: true 14 | ``` 15 | 16 | ## Example 2: 17 | 18 | ``` 19 | Input: s = "rat", t = "car" 20 | Output: false 21 | ``` 22 | 23 | ### Note: 24 | 25 | You may assume the string contains only lowercase alphabets. 26 | 27 | ### Follow up: 28 | 29 | What if the inputs contain unicode characters? How would you adapt your solution to such case? 30 | 31 | ## Solution (only lowercase alphabets -- Array) 32 | 33 | - use an array of size 26, to count the frequency of each alphabet 34 | - sweep through first string and increment the count for each alphabet 35 | - sweep through second string and decrement the count for each alphabet 36 | - check the counter array, if every value in the array is 0, then the strings are an anagram 37 | 38 | ## Complexity Analysis (only lowercase alphabets -- Array): 39 | 40 | - **Time complexity** : `O(len(string))`. We have to sweep through the entire string. 41 | 42 | - **Space complexity** : `O(1)`. The size of the counter array is always 26. Does not scale with the size of the string. 43 | 44 | ## Solution (when its unicode characters -- Hashmap) 45 | 46 | - Count the frequency of each character in first string. ( use hashmap ) `O(n)` 47 | - For Second string, check if each character in the string `O(n)` exists in the hashmap `O(1)` 48 | - If yes, `O(1)` 49 | - If count is already 0. Then its not an anagram. 50 | - Else, decrement the count by 1 51 | - If no, Then its not an anagram. `O(n)` 52 | 53 | ## Complexity Analysis (when its unicode characters -- Hashmap): 54 | 55 | - **Time complexity** : `O(len(string))`. We have to sweep through the entire string. 56 | 57 | - **Space complexity** : `O(len(string))`. The size of the hashmap, to fit in all the unicode characters present it. in worst case, when every character is unique, the space becomes `len(string)` 58 | 59 | #### [LeetCode link](https://leetcode.com/problems/valid-anagram/) 60 | -------------------------------------------------------------------------------- /01_Strings/isAnagram/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @param {string} t 4 | * @return {boolean} 5 | */ 6 | var isAnagram = function (s, t) { 7 | if (s.length != t.length) { 8 | return false; 9 | } 10 | const aCharCode = "a".charCodeAt(0); 11 | // every char is "a" to "z" so assume its 26, initialse with 0s 12 | const table = Array.from(Array(26), () => 0); 13 | for (let i = 0; i < s.length; i++) { 14 | // charCode - charCode gives a value between 0-25 15 | table[s.charCodeAt(i) - aCharCode]++; 16 | table[t.charCodeAt(i) - aCharCode]--; 17 | } 18 | // every number in the table must be exactly zero, only then its an anagram 19 | return table.every((count) => count === 0); 20 | }; 21 | 22 | // Hashmap solution 23 | var isAnagram = function (s, t) { 24 | if (s.length != t.length) { 25 | return false; 26 | } 27 | const map = new Map(); 28 | for (let i = 0; i < s.length; i++) { 29 | const char = s[i]; 30 | const prevCount = map.get(char) ?? 0; 31 | map.set(char, prevCount + 1); 32 | } 33 | for (let i = 0; i < t.length; i++) { 34 | const char = t[i]; 35 | const prevCount = map.get(char) ?? 0; 36 | // when 0, the character is not present in the previous string 37 | // or there is extra in this string 38 | // so when 0, its not an anagram 39 | if (prevCount === 0) return false; 40 | map.set(char, prevCount - 1); 41 | } 42 | return true; 43 | }; 44 | -------------------------------------------------------------------------------- /01_Strings/isPalindrome/README.md: -------------------------------------------------------------------------------- 1 | ## Is Palindrome 2 | ``` 3 | Check if String is a palindrome 4 | 5 | ``` 6 | 7 | > A palindrome is a word which reads the same backward or forward. 8 | -------------------------------------------------------------------------------- /01_Strings/isPalindrome/Solution.py: -------------------------------------------------------------------------------- 1 | 2 | def isPalindrome(str): 3 | l = len(str) 4 | if l == 0 or l == 1: 5 | return True 6 | mid = l / 2 7 | high = l - 1 8 | low = 0 9 | for i in range(mid): 10 | if str[low] != str[high]: 11 | return False 12 | high -= 1 13 | low += 1 14 | return True 15 | 16 | def main(): 17 | print "checking for Palindrome" 18 | assert isPalindrome("level") == True 19 | assert isPalindrome('malayalam') == True 20 | assert isPalindrome('abcs') == False 21 | assert isPalindrome('a') == True 22 | print 'all is well :)' 23 | 24 | if __name__ == '__main__': 25 | main() -------------------------------------------------------------------------------- /01_Strings/longest-substring-without-repeating-characters/README.md: -------------------------------------------------------------------------------- 1 | # Longest Substring Without Repeating Characters 2 | 3 | ![Medium difficulty](https://img.shields.io/badge/difficulty-medium-yellow) 4 | 5 | Given a string, find the length of the longest substring without repeating characters. 6 | 7 | ## Example 1: 8 | 9 | ``` 10 | Input: "abcabcbb" 11 | Output: 3 12 | Explanation: The answer is "abc", with the length of 3. 13 | ``` 14 | 15 | ## Example 2: 16 | 17 | ``` 18 | Input: "bbbbb" 19 | Output: 1 20 | Explanation: The answer is "b", with the length of 1. 21 | ``` 22 | 23 | ## Example 3: 24 | 25 | ``` 26 | Input: "pwwkew" 27 | Output: 3 28 | Explanation: The answer is "wke", with the length of 3. 29 | Note that the answer must be a substring, "pwke" is a subsequence and not a substring. 30 | ``` 31 | 32 | ## Complexity Analysis (HashMap approach): 33 | 34 | - **Time complexity** : `O(n)`. We sweep through the list once 35 | 36 | - **Space complexity** : `O(n)`. The size of the hashmap can be all the elements in the whole array if they are unique 37 | 38 | ## Complexity Analysis (HashSet approach): 39 | 40 | - **Time complexity** : **`O(2n) = O(n)`**. In the worst case each character will be visited twice by `left_pointer` and `right_pointer`. 41 | 42 | - **Space complexity** : `O(n)`. The size of the hashset can be all the elements in the whole array if they are unique 43 | 44 | #### [LeetCode link](https://leetcode.com/problems/longest-substring-without-repeating-characters) 45 | #### [LeetCode discussion](https://leetcode.com/problems/longest-substring-without-repeating-characters/discuss/1729/11-line-simple-Java-solution-O(n)-with-explanation) -------------------------------------------------------------------------------- /01_Strings/longest-substring-without-repeating-characters/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} s 3 | * @return {number} 4 | */ 5 | var lengthOfLongestSubstring_Map = function(s) { 6 | let maxCount = 0 7 | let left = 0 8 | // chars in the strings to their latest indexes 9 | const map = new Map() 10 | 11 | for (let right = 0; right < s.length; right++) { 12 | if (map.has(s[right])) { 13 | const duplicate_index = map.get(s[right]) 14 | // use max here to ensure that left doesnt go back 15 | left = Math.max(left, duplicate_index + 1) 16 | } 17 | // if there was a duplicate, the index is updated thats it 18 | map.set(s[right], right) 19 | // always calculate the max count 20 | const count = right - left + 1 21 | maxCount = Math.max(count, maxCount) 22 | } 23 | return maxCount 24 | }; 25 | 26 | var lengthOfLongestSubstring_Set = function(s) { 27 | let maxCount = 0 28 | // set comprising unique characters in the window 29 | const set = new Set() 30 | const N = s.length 31 | let left = 0 32 | let right = 0 33 | while (right < N) { 34 | if (set.has(s[right])) { 35 | // keep on deleting items on the set based on the left window index, until we find the substring start where there is no repeating character 36 | set.delete(s[left]) 37 | left++ 38 | } else { 39 | // the character is unique, add to substring found 40 | set.add(s[right]) 41 | // get the current substring size and compare to max 42 | maxCount = Math.max(maxCount, set.size) 43 | // increment right window 44 | right++ 45 | } 46 | } 47 | return maxCount 48 | }; -------------------------------------------------------------------------------- /01_Strings/shortestPalindrome/README.md: -------------------------------------------------------------------------------- 1 | ## Shortest Palindrome 2 | ``` 3 | 4 | Find the shortest palindrome in a String 5 | 6 | ``` -------------------------------------------------------------------------------- /01_Strings/shortestPalindrome/Solution.py: -------------------------------------------------------------------------------- 1 | def isPalindrome(str): 2 | l = len(str) 3 | if l == 0 or l == 1: 4 | return True 5 | mid = l / 2 6 | high = l - 1 7 | low = 0 8 | for i in range(mid): 9 | if str[low] != str[high]: 10 | return False 11 | high -= 1 12 | low += 1 13 | return True 14 | 15 | def shortestPalindrome(str): 16 | if len(str) == 0 or len(str) == 1: 17 | return str 18 | for i in range(len(str)): 19 | temp = str + str[0:i][::-1] # [::-1] is to reverse the string 20 | if isPalindrome(temp): 21 | return temp 22 | 23 | 24 | def main(): 25 | print 'testing Palindrome' 26 | assert shortestPalindrome('aaab') == 'aaabaaa' 27 | assert shortestPalindrome('a') == 'a' 28 | assert shortestPalindrome('aa') == 'aa' 29 | assert shortestPalindrome('tim') == 'timit' 30 | assert shortestPalindrome('') == '' 31 | print 'all is well :)' 32 | if __name__ == '__main__': 33 | main() -------------------------------------------------------------------------------- /02_LinkedLists/LoopInList/README.md: -------------------------------------------------------------------------------- 1 | ## Q1 : How to check whether there is a loop in a linked list? 2 | 3 | For example, the list in the Figure below has a loop. 4 | 5 | ![Figure-1](http://3.bp.blogspot.com/-Wp_2IFN624w/TxQ4Dcqg-OI/AAAAAAAABGo/QztnZcdLK48/s1600/29_Figure1.PNG) 6 | 7 | ### Solution 8 | Two pointers are initialized at the head of list. One pointer forwards once at each step, and the other forwards twice at each step. If the faster pointer meets the slower one again, there is a loop in the list. Otherwise there is no loop if the faster one reaches the end of list. 9 | 10 | ``` cpp 11 | bool hasLoop(struct node *head) 12 | { 13 | struct node *pslow = head; 14 | struct node *pfast = head; 15 | while(pfast != NULL && pfast->next != NULL) 16 | { 17 | pslow = pslow->next; 18 | pfast = pfast->next->next; 19 | if(pslow == pfast) 20 | return true; 21 | } 22 | return false; 23 | } 24 | 25 | ``` 26 | ## Q2: If there is a loop in a linked list, how to get the entry node of the loop? 27 | 28 | > The entry node is the first node in the loop from head of list. For instance, the entry node of loop in the list of Figure 1 is the node with value 3. 29 | 30 | #### [LeetCode link](https://leetcode.com/problems/linked-list-cycle/) 31 | 32 | #### [Detailed discussion](http://k2code.blogspot.in/2010/04/how-would-you-detect-loop-in-linked.html) 33 | -------------------------------------------------------------------------------- /02_LinkedLists/LoopInList/helperFuncs.cpp: -------------------------------------------------------------------------------- 1 | 2 | struct node* BuildOneToSixWithLoop() { 3 | struct node* head = NULL; 4 | head = malloc(sizeof(struct node)); 5 | head->data = 2; 6 | struct node* current = head; 7 | struct node* loopEntry = NULL; 8 | // loop is from 6->3 9 | for(int d=2; d<=6; d++) { 10 | current->next = malloc(sizeof(struct node)); 11 | current->next->data = d; 12 | current = current->next; 13 | if (d == 3) loopEntry = current; 14 | } 15 | current->next = loopEntry; // current now points to {6} 16 | return head; 17 | } 18 | 19 | void printLinkedList(struct node* head) { 20 | // add a set to check the loop and then stop printing || NULL ! 21 | struct node* current = head; 22 | printf("\n"); 23 | while (current != NULL) { 24 | printf( "(%d) -> ", current->data ); 25 | current = current->next; 26 | } 27 | printf("NULL\n"); 28 | } 29 | -------------------------------------------------------------------------------- /02_LinkedLists/LoopInList/main.cpp: -------------------------------------------------------------------------------- 1 | struct node { 2 | int data; 3 | struct node *next; 4 | } 5 | 6 | bool hasLoop(struct node *head) 7 | { 8 | struct node *pslow = head; 9 | struct node *pfast = head; 10 | while(pfast != NULL && pfast->next != NULL) 11 | { 12 | pslow = pslow->next; 13 | pfast = pfast->next->next; 14 | if(pslow == pfast) 15 | return true; 16 | } 17 | return false; 18 | } 19 | 20 | int main() { 21 | 22 | } 23 | -------------------------------------------------------------------------------- /02_LinkedLists/README.md: -------------------------------------------------------------------------------- 1 | # LinkedLists 2 | 1. Write code to remove duplicates from an unsorted linked list. 3 | * FOLLOW UP, How would you solve this problem if a temporary buffer is not allowed? 4 | 2. Implement an algorithm to find the kth to last element of a singly linked list. 5 | 3. Implement an algorithm to delete a node in the middle of a singly linked list, given only access to that node. 6 | * EXAMPLE 7 | * Input: the node `c` from the linked list `a->b->c->d->e` 8 | * Result: nothing is returned, but the new linked list looks like `a->b->d->e` 9 | 4. Write code to partition a linked list around a value `x`, such that all nodes less than `x` come before all nodes greater than or equal to `x`. 10 | 5. You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.**[add-two-numbers](add-two-numbers)** 11 | 6. Given a circular linked list, implement an algorithm which returns node at the beginning of the loop.**[LoopInList](LoopInList)** 12 | * DEFINITION 13 | * Circular linked list: A (corrupt) linked list in which a node’s next pointer points to an earlier node, so as to make a loop in the linked list. 14 | * EXAMPLE 15 | * input: A -> B -> C -> D -> E -> C [the same C as earlier] 16 | * output: C 17 | 7. Implement a function to check if linkedlist is a palindrome. **[isPalindrome](isPalindrome)** 18 | 8. Write a function to remove a single occurrence of an integer from a doubly linked list if it is present. **[doubleLinkDel](doubleLinkDel)** 19 | 9. Delete the Node at a Particular Position in a Linked List. **[delAtPosition](delAtPosition)** 20 | 10. Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. **[merge-two-sorted-lists](merge-two-sorted-lists)** 21 | 11. Reverse a singly linked list. **[reverse-linked-list](reverse-linked-list)** 22 | 12. Merge k sorted linked lists and return it as one sorted list. **[merge-k-sorted-lists](merge-k-sorted-lists)** 23 | 24 | > Questions 1 to 7 have been taken from [Cracking the Coding Interview](http://www.amazon.com/Cracking-Coding-Interview-6th-Edition/dp/0984782850) 25 | 26 | > Questions 10, 11 are in [Team blind's curated list of 75 questions from leetcode](https://github.com/AlgorithmCrackers/Interview-Questions/issues/28) 27 | 28 | -------------------------------------------------------------------------------- /02_LinkedLists/ReverseLinkedList/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | Reverse a Linked List 3 | 4 | 1) Recurrence method 5 | 2) Iterative method 6 | ``` 7 | -------------------------------------------------------------------------------- /02_LinkedLists/ReverseLinkedList/ReverseList.java: -------------------------------------------------------------------------------- 1 | class ReverseList{ 2 | ListNode head; 3 | 4 | 5 | //recursive method 6 | public static void reverseListRec(ListNode cur) { 7 | if(cur == null) return; //null checking 8 | 9 | // Base case: tail of the list 10 | if(cur.next == null) { 11 | head = cur; 12 | return; 13 | } 14 | reverseListRec(cur.next); 15 | // set the second element pointing to first element 16 | cur.next.next = cur; 17 | 18 | //remove the current element next value 19 | cur.next = null; 20 | } 21 | 22 | //Iterative method 23 | public static void reverseListIter(ListNode head) { 24 | ListNode prev = null; 25 | ListNode cur = head; 26 | ListNode next = null; 27 | while(cur != null) { 28 | next = cur.next; 29 | cur.next = prev; 30 | prev = cur; 31 | cur = next; 32 | } 33 | 34 | // return prev; if return is Head node then use this 35 | head = prev; //sets the last prev node to head 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /02_LinkedLists/ReverseLinkedList/ReverseList.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution(object): 8 | def reverseList(self, head): 9 | """ 10 | :type head: ListNode 11 | :rtype: ListNode 12 | """ 13 | if head == None: 14 | return ListNode(None) 15 | cur = head 16 | n = prev = 0 17 | while cur.next != None: 18 | n = cur.next 19 | cur.next = prev 20 | prev = cur 21 | cur = n 22 | return prev 23 | 24 | -------------------------------------------------------------------------------- /02_LinkedLists/SortList/README.md: -------------------------------------------------------------------------------- 1 | ##Question 2 | ``` 3 | Sort a linked list in O(n log n) time using constant space complexity. 4 | ``` -------------------------------------------------------------------------------- /02_LinkedLists/SortList/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { 7 | * val = x; 8 | * next = null; 9 | * } 10 | * } 11 | */ 12 | public class Solution { 13 | public ListNode sortList(ListNode head) { 14 | if(head == null || head.next == null) return head; 15 | 16 | ListNode mid = findMid(head); 17 | ListNode r = mid.next; 18 | //divide step 19 | mid.next = null; 20 | 21 | ListNode l = sortList(head); 22 | r = sortList(r); 23 | return merge(l, r); 24 | } 25 | //merge step 26 | public ListNode merge(ListNode l, ListNode r) { 27 | ListNode dummy = new ListNode(0); 28 | ListNode cur = dummy; 29 | while(l != null && r != null) { 30 | if(l.val < r.val) { 31 | cur.next = l; 32 | l = l.next; 33 | } else { 34 | cur.next = r; 35 | r = r.next; 36 | } 37 | cur = cur.next; 38 | } 39 | if(l != null) { 40 | cur.next = l; //append the remaining list to cur 41 | } else { 42 | cur.next = r; 43 | } 44 | return dummy.next; 45 | } 46 | 47 | public ListNode findMid(ListNode head) { 48 | if(head == null) return null; 49 | if(head.next == null) return head; 50 | ListNode slow = head; 51 | ListNode fast = head.next; 52 | //fast jumps everytime twice so it goes to half 53 | while(fast != null && fast.next != null) { 54 | fast = fast.next.next; 55 | slow = slow.next; 56 | } 57 | return slow; 58 | } 59 | } -------------------------------------------------------------------------------- /02_LinkedLists/add-two-numbers/README.md: -------------------------------------------------------------------------------- 1 | # Add Two Numbers 2 | 3 | `Medium` 4 | 5 | You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. 6 | 7 | You may assume the two numbers do not contain any leading zero, except the number 0 itself. 8 | 9 | ## Example: 10 | 11 | ``` 12 | Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) 13 | Output: 7 -> 0 -> 8 14 | Explanation: 342 + 465 = 807. 15 | ``` 16 | 17 | ## Complexity Analysis: 18 | 19 | - **Time complexity** : `O(max(m, n))`. Assume that `m` and `n` are lengths of the two input linked-lists respectively. We traverse the linked-list with the maximum length once. 20 | 21 | - **Space complexity** : `O(max(m, n))`. The length of the new list is the maximum length of the two lists + 1 (for the carry over). 22 | 23 | #### [LeetCode link](https://leetcode.com/problems/add-two-numbers/) -------------------------------------------------------------------------------- /02_LinkedLists/add-two-numbers/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} l1 10 | * @param {ListNode} l2 11 | * @return {ListNode} 12 | */ 13 | const addTwoNumbers = function(l1, l2) { 14 | let current = new ListNode(-1) 15 | const ptrToFake = current 16 | // variable to store the carry over after addition (either 1 or 0) 17 | let carry = 0 18 | while(l1 || l2) { 19 | const a = l1 ? l1.val : 0 20 | const b = l2 ? l2.val : 0 21 | // actual summing 22 | sum = carry + a + b 23 | // find the carry over 24 | carry = sum > 9 ? 1 : 0 25 | // the mod to 10 is the required number to store in the node 26 | // example: 9 + 8 = 17, here 7 will be in the node, 1 goes to carry over 27 | const node = new ListNode(sum % 10) 28 | // add to the resulting linked list 29 | current.next = node 30 | // iterate to the next nodes 31 | current = node 32 | if (l1) { 33 | l1 = l1.next 34 | } 35 | if (l2) { 36 | l2 = l2.next 37 | } 38 | } 39 | 40 | // finally, check if the carry was left over.. this means we need an extra 1 41 | if (carry) { 42 | const node = new ListNode(1) 43 | current.next = node 44 | } 45 | 46 | return ptrToFake.next 47 | }; -------------------------------------------------------------------------------- /02_LinkedLists/delAtPosition/README.md: -------------------------------------------------------------------------------- 1 | Given a singly-linked list, implement a method to delete the node at a given position (starting from 1 as the head position) and return the head of the list. Do nothing if the input position is out of range. 2 | 3 | ``` 4 | Examples: 5 | 6 | LinkedList: 1->2->3->4 , Head = 1 7 | 8 | deleteAtMiddle(Head,3) ==> 1->2->4 9 | ``` 10 | -------------------------------------------------------------------------------- /02_LinkedLists/delAtPosition/Solution.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | class ListNode { 3 | int data; 4 | ListNode next; 5 | ListNode(int data) { this.data = data; } 6 | } 7 | 8 | public ListNode deleteAtPos(ListNode head, int position) { 9 | if (position == 1) { 10 | if (head != null) head = head.next; 11 | return head; 12 | } 13 | ListNode curr = head; 14 | ListNode prevNode = curr; 15 | int count = 0; 16 | while(curr != null) { 17 | count++; 18 | if(count == position) { 19 | prevNode.next = curr.next; 20 | curr.next = null; 21 | } 22 | else { 23 | prevNode = curr; 24 | curr = curr.next; 25 | } 26 | } 27 | return head; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /02_LinkedLists/doubleLinkDel/Solution.java: -------------------------------------------------------------------------------- 1 | 2 | 3 | class Solution { 4 | static void delFirstOccurence(LinkedListNode head, int data){ 5 | LinkedListNode cur = head; 6 | while(cur != null){ 7 | if(cur.data == data) { // found the first occurence 8 | if(cur.prev != null) { 9 | cur.prev.next = cur.next; 10 | } 11 | if(cur.next != null) { 12 | cur.next.prev = cur.prev; 13 | } 14 | return; 15 | } 16 | cur = cur.next; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /02_LinkedLists/isPalindrome/README.md: -------------------------------------------------------------------------------- 1 | # Palindrome Linked List 2 | 3 | `Easy` 4 | 5 | Given a singly linked list, determine if it is a palindrome. 6 | 7 | ## Example 1: 8 | 9 | ``` 10 | Input: 1->2 11 | Output: false 12 | ``` 13 | 14 | ## Example 2: 15 | 16 | ``` 17 | Input: 1->2->2->1 18 | Output: true 19 | ``` 20 | 21 | ## Follow up: 22 | Could you do it in O(n) time and O(1) space? 23 | 24 | ## Complexity Analysis: 25 | 26 | - **Time complexity** : `O(n)`. We traverse the linked-list containing *n* elements only once. The reverse operation costs `O(n/2)` time. Totally it is `O(n) + O(n/2) = O(n)` 27 | 28 | - **Space complexity** : `O(1)`. The extra space is only the variables for fast and slow pointer. Also the reverse operation takes `O(1)` time 29 | 30 | #### [LeetCode link](https://leetcode.com/problems/palindrome-linked-list/) 31 | #### [YouTube explanation](https://www.youtube.com/watch?v=wk4QsvwQwdQ) 32 | -------------------------------------------------------------------------------- /02_LinkedLists/isPalindrome/Solution.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * public class ListNode { 4 | * int val; 5 | * ListNode next; 6 | * ListNode(int x) { val = x; } 7 | * } 8 | */ 9 | class Solution { 10 | // reverse the linked-list 11 | private static ListNode reverse(ListNode head) { 12 | ListNode prev = null; 13 | while (head != null) { 14 | ListNode next = head.next; 15 | head.next = prev; 16 | prev = head; 17 | head = next; 18 | } 19 | return prev; 20 | } 21 | 22 | // EVEN: 1 -> 2 -> 3 -> 3 -> 2 -> 1 23 | // slow will be at the 2nd 3 when while loop ends 24 | // ODD: 1 -> 2 -> 3 -> 4 -> 3 -> 2 -> 1 25 | // slow will be at the 4 when while loop ends 26 | public boolean isPalindrome(ListNode head) { 27 | ListNode fast = head; 28 | ListNode slow = head; 29 | while (fast != null && fast.next != null) { 30 | fast = fast.next.next; 31 | slow = slow.next; 32 | } 33 | // slow is at the middle now 34 | // for EVEN always at the 2nd place.. say for size 6.. slow ends up at 3rd index not the 2nd index 35 | // for ODD always at the middle .. say for size 7.. slow ends up at 3rd index, exactly middle.. has the extra element so comparision not needed for the last element 36 | ListNode reversed = reverse(slow); 37 | // reversed has the half no of elements so need to check if they are equal, thats it 38 | // the no if elements in head is always greater than of reversed 39 | while (reversed != null) { 40 | if (reversed.val != head.val) { 41 | return false; 42 | } 43 | reversed = reversed.next; 44 | head = head.next; 45 | } 46 | return true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /02_LinkedLists/isPalindrome/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {boolean} 11 | */ 12 | 13 | // reverse the linked-list 14 | const reverse = function(head) { 15 | let prev = null 16 | while(head) { 17 | const next = head.next 18 | head.next = prev 19 | prev = head 20 | head = next 21 | } 22 | return prev 23 | }; 24 | 25 | // EVEN: 1 -> 2 -> 3 -> 3 -> 2 -> 1 26 | // slow will be at the 2nd 3 when while loop ends 27 | // ODD: 1 -> 2 -> 3 -> 4 -> 3 -> 2 -> 1 28 | // slow will be at the 4 when while loop ends 29 | const isPalindrome = function(head) { 30 | let fast = head 31 | let slow = head 32 | while (fast !== null && fast.next !== null) { 33 | fast = fast.next.next 34 | slow = slow.next 35 | } 36 | // slow is at the middle now 37 | // for EVEN always at the 2nd place.. say for size 6.. slow ends up at 3rd index not the 2nd index 38 | // for ODD always at the middle .. say for size 7.. slow ends up at 3rd index, exactly middle.. has the extra element so comparision not needed for the last element 39 | let reversed = reverse(slow) 40 | // reversed has the half no of elements so need to check if they are equal, thats it 41 | // the no if elements in head is always greater than of reversed 42 | while (reversed) { 43 | if (reversed.val !== head.val) { 44 | return false 45 | } 46 | reversed = reversed.next 47 | head = head.next 48 | } 49 | return true 50 | }; -------------------------------------------------------------------------------- /02_LinkedLists/merge-k-sorted-lists/README.md: -------------------------------------------------------------------------------- 1 | ## Merge k Sorted Lists 2 | 3 | ![Difficulty-Hard](https://img.shields.io/badge/Difficulty-Hard-red) 4 | 5 | ![Divide and conquer Technique](https://img.shields.io/badge/Technique-Divide_and_conquer-blue) 6 | 7 | Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. 8 | 9 | ## Example: 10 | 11 | ``` 12 | Input: 13 | [ 14 | 1->4->5, 15 | 1->3->4, 16 | 2->6 17 | ] 18 | Output: 1->1->2->3->4->4->5->6 19 | ``` 20 | 21 | ## Complexity Analysis (Divide and conquer): 22 | 23 | - **Time complexity** : `O(n * log(k))`. We divide each problem by half. Making it `log(k)` steps. In each step we do `O(n)` work. Where `n` is the number of nodes in a linked-list. Same as `merge sort` complexity analysis. 24 | 25 | - **Space complexity** : `O(log(k))`. Stack space to keep on dividing in half. Same as `merge sort` complexity analysis. -------------------------------------------------------------------------------- /02_LinkedLists/merge-k-sorted-lists/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode[]} lists 10 | * @return {ListNode} 11 | */ 12 | 13 | const mergeTwoLists = (list1, list2) => { 14 | let fake = new ListNode(-1) 15 | const ptrToFake = fake 16 | while(list1 && list2) { 17 | if (list1.val < list2.val) { 18 | fake.next = list1 19 | list1 = list1.next 20 | } else { 21 | fake.next = list2 22 | list2 = list2.next 23 | } 24 | fake = fake.next 25 | } 26 | 27 | if (list1) { 28 | fake.next = list1 29 | } 30 | 31 | if (list2) { 32 | fake.next = list2 33 | } 34 | 35 | return ptrToFake.next 36 | } 37 | 38 | 39 | var mergeKLists = function(lists) { 40 | if (!lists || lists.length === 0) return null 41 | if (lists.length === 1) return lists[0] 42 | 43 | // split array in half 44 | const halfwayThrough = Math.floor(lists.length / 2) 45 | 46 | const arrayFirstHalf = lists.slice(0, halfwayThrough) 47 | const arraySecondHalf = lists.slice(halfwayThrough, lists.length) 48 | 49 | // do work for each halfs 50 | const mergedLeft = mergeKLists(arrayFirstHalf) 51 | const mergedRight = mergeKLists(arraySecondHalf) 52 | // merge the halfs 53 | return mergeTwoLists(mergedLeft, mergedRight) 54 | 55 | }; -------------------------------------------------------------------------------- /02_LinkedLists/merge-two-sorted-lists/README.md: -------------------------------------------------------------------------------- 1 | # Merge Two Sorted Lists 2 | 3 | Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 4 | 5 | [Leetcode link](https://leetcode.com/problems/merge-two-sorted-lists/) 6 | 7 | ## Example: 8 | 9 | ``` 10 | Input: 1->2->4, 1->3->4 11 | Output: 1->1->2->3->4->4 12 | ``` 13 | 14 | ## Solution 15 | 16 | The key to solve the problem is defining a **fake head**. Then compare the first elements from each list. Add the smaller one to the merged list. Finally, when one of them is empty, simply append it to the merged list, since it is already sorted. 17 | 18 | ## Complexity Analysis: 19 | 20 | - **Time complexity** : `O(n)`. We traverse each the lists only once. Each comparision for minimum costs only `O(1)` time. 21 | 22 | - **Space complexity** : `O(1)`. The extra space required is only the fake node. 23 | -------------------------------------------------------------------------------- /02_LinkedLists/merge-two-sorted-lists/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} l1 10 | * @param {ListNode} l2 11 | * @return {ListNode} 12 | */ 13 | var mergeTwoLists = function(l1, l2) { 14 | // create a fake element, we can discard it later 15 | let ans = new ListNode(-1) 16 | // store the pointer to the fake node (the next pointer is the pointer to our result linked list) 17 | let temp = ans 18 | while (l1 && l2) { 19 | // find what is minimum and point that 20 | // increment the linked list where we got the minimum from 21 | if (l1.val < l2.val) { 22 | ans.next = l1 23 | l1 = l1.next 24 | } else { 25 | ans.next = l2 26 | l2 = l2.next 27 | } 28 | // increment our result linked list 29 | ans = ans.next 30 | } 31 | // find which linked list must still be added to the result 32 | if (l1) { 33 | ans.next = l1; 34 | } 35 | if (l2) { 36 | ans.next = l2; 37 | } 38 | // the next pointer to our fake node is our result 39 | return temp.next 40 | }; 41 | -------------------------------------------------------------------------------- /02_LinkedLists/reverse-linked-list/README.md: -------------------------------------------------------------------------------- 1 | # Reverse Linked List 2 | 3 | Reverse a singly linked list. 4 | 5 | ## Example: 6 | 7 | ``` 8 | Input: 1->2->3->4->5->NULL 9 | Output: 5->4->3->2->1->NULL 10 | ``` 11 | 12 | ### Follow up: 13 | 14 | A linked list can be reversed either iteratively or recursively. Could you implement both? 15 | 16 | ## Complexity Analysis (Iterative): 17 | 18 | - **Time complexity** : `O(n)`. We traverse the linked-list containing *n* elements only once. The swap operation costs `O(1)` time. 19 | 20 | - **Space complexity** : `O(1)`. The extra space is only the one to store the result and the one temporary variable inside the loop. 21 | 22 | ## Complexity Analysis (Recursive): 23 | 24 | - **Time complexity** : `O(n)`. We traverse the linked-list containing *n* elements only once. The swap operation costs `O(1)` time. 25 | 26 | - **Space complexity** : **`O(n)`**. The extra space is the stack space. When reaching the last part of the linked-list the whole stack upto the previous node is stored. 27 | 28 | ### [Leetcode Problem](https://leetcode.com/problems/reverse-linked-list/) 29 | -------------------------------------------------------------------------------- /02_LinkedLists/reverse-linked-list/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for singly-linked list. 3 | * function ListNode(val) { 4 | * this.val = val; 5 | * this.next = null; 6 | * } 7 | */ 8 | /** 9 | * @param {ListNode} head 10 | * @return {ListNode} 11 | */ 12 | var reverseListRecursive = function(head) { 13 | // base case 14 | if (head === null || head.next === null) return head 15 | // save next 16 | const temp = head.next 17 | // get the rest of the linked-list reversed 18 | const reversed = reverseList(head.next) 19 | // the last portion of the reversed list should point to the head 20 | temp.next = head 21 | // reset the head's next 22 | head.next = null 23 | return reversed 24 | 25 | }; 26 | 27 | var reverseList = function(head) { 28 | let resultHead = null // keeps tracks of the result's head 29 | while (head) { 30 | // save the next 31 | const temp = head.next 32 | // make the next to be the current resultHead (actual reverse) 33 | head.next = resultHead 34 | // make the next resultHead to be the current node 35 | resultHead = head 36 | // the next iteration 37 | head = temp 38 | } 39 | return resultHead 40 | }; 41 | -------------------------------------------------------------------------------- /03_Stacks_and_Queues/Has_redundats(s)/README.md: -------------------------------------------------------------------------------- 1 | Check if the input string has redundant braces 2 | === 3 | 4 | [Career Cup Question Link](http://www.careercup.com/question?id=5769760746766336) 5 | 6 | For example, 7 | ``` 8 | ((a+b)) - Has redundant braces. 9 | (a+(b+c)) - This doesn't has redundant braces. 10 | ``` 11 | -------------------------------------------------------------------------------- /03_Stacks_and_Queues/Has_redundats(s)/has_redundant(s).py: -------------------------------------------------------------------------------- 1 | def has_redundant(s): 2 | stack = [0] 3 | for c in s: 4 | if c == '(': 5 | stack.append(0) 6 | elif c == ')': 7 | if stack.pop() == 0: 8 | return True 9 | else: 10 | stack[-1] += 1 11 | # Treat (expr) as redundant 12 | return stack.pop() == 0 13 | 14 | assert has_redundant("()") 15 | assert has_redundant("(a+b)") 16 | assert not has_redundant("(a+b)+c") 17 | assert has_redundant("((a+b))+c") -------------------------------------------------------------------------------- /03_Stacks_and_Queues/Has_redundats(s)/main.py: -------------------------------------------------------------------------------- 1 | def has_redundant(s): 2 | stack = [0] 3 | for c in s: 4 | if c == '(': 5 | stack.append(0) 6 | elif c == ')': 7 | if stack.pop() == 0: # if there are braces without alphanum char inbetween 8 | return True 9 | else: 10 | stack[-1] += 1 # if a alphanum char occurs increment the last elem of the list 11 | # Treat (expr) as redundant 12 | return stack.pop() == 0 # (expr)+expr returns false 13 | 14 | def main(): 15 | assert has_redundant("()") 16 | assert has_redundant("(a+b)") 17 | assert not has_redundant("(a+b)+c") 18 | assert has_redundant("((a+b))+c") 19 | print "\nAll asserts PASSED!!, Yaaaaaay!!\n" 20 | 21 | if __name__ == "__main__": 22 | main() 23 | 24 | -------------------------------------------------------------------------------- /03_Stacks_and_Queues/MissingNoFromStack/MissingNoFromStack.java: -------------------------------------------------------------------------------- 1 | import java.util.Iterator; 2 | import java.util.Stack; 3 | /* 4 | * Find out missing no. from a stack if two given stacks have same numbers. 5 | */ 6 | 7 | public class MissingNoFromStack { 8 | /* 9 | * @param: stack1 10 | * @param: stack2 11 | */ 12 | public static int missingNumber(Stack st, Stack st2) { 13 | int res1 = missingHelper(st); 14 | int res2 = missingHelper(st2); 15 | 16 | return res1 ^ res2; 17 | } 18 | /* 19 | * computes the Exor of all the elements of Stack 20 | * @param: Stack 21 | */ 22 | public static int missingHelper(Stack st) { 23 | Iterator it = st.iterator(); 24 | int res = 0; 25 | while(it.hasNext()) { 26 | res = res ^ it.next(); // exor all the elements 27 | } 28 | return res; 29 | } 30 | public static void main(String[] args) { 31 | Stack st = new Stack(); 32 | st.add(2); 33 | st.add(3); 34 | st.add(40); 35 | Stack st2 = new Stack(); 36 | st.add(2); 37 | st.add(3); 38 | int missingNo = missingNumber(st, st2); 39 | assert(missingNo == 40); 40 | System.out.print("Success " ); 41 | 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /03_Stacks_and_Queues/Queue/README.md: -------------------------------------------------------------------------------- 1 | ## Implement Queue 2 | ``` 3 | Implement a queue with queue and dequeue functions 4 | ``` -------------------------------------------------------------------------------- /03_Stacks_and_Queues/Queue/queue.py: -------------------------------------------------------------------------------- 1 | class Queue(object): 2 | def __init__(self): 3 | self.container = [] 4 | 5 | # [1, 2] => [1, 2, 3] 6 | # adds element at the starting 7 | def enqueue(self, item): 8 | self.container.append(item) 9 | 10 | # [1, 2, 3] => [2, 3] 11 | # removes the element at starting 12 | def dequeue(self): 13 | if(self.isEmpty()): 14 | print 'deque operation is not permitted in the emplty container' 15 | return 16 | else: 17 | return self.container.pop(0) 18 | 19 | 20 | def isEmpty(self): 21 | return len(self.container) == 0 22 | 23 | def display(self): 24 | print self.container 25 | 26 | def main(): 27 | q = Queue() 28 | q.enqueue(1) 29 | q.enqueue(2) 30 | q.enqueue(3) 31 | q.display() 32 | assert q.dequeue() == 1 33 | assert q.isEmpty() == False 34 | assert q.dequeue() == 2 35 | assert q.dequeue() == 3 36 | assert q.isEmpty() == True 37 | print 'all is well :)' 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /03_Stacks_and_Queues/QueueUsingStack/QueueUsingStack.java: -------------------------------------------------------------------------------- 1 | /* package whatever; // don't place package name! */ 2 | 3 | import java.util.*; 4 | import java.lang.*; 5 | import java.io.*; 6 | 7 | /* Name of the class has to be "Main" only if the class is public. */ 8 | class QueueUsingStack 9 | { 10 | private Stack st; 11 | public QueueUsingStack() { 12 | st = new Stack(); 13 | } 14 | 15 | public void enqueue(Integer data) { 16 | if(st.isEmpty()) { 17 | st.push(data); 18 | return; 19 | } 20 | Integer topElement = st.pop(); 21 | enqueue(data); 22 | st.push(topElement); 23 | } 24 | 25 | public Integer dequeue() { 26 | return st.pop(); 27 | } 28 | public static void main (String[] args) throws java.lang.Exception 29 | { 30 | // your code goes here 31 | QueueUsingStack q = new QueueUsingStack(); 32 | q.enqueue(1); 33 | q.enqueue(2); 34 | q.enqueue(3); 35 | System.out.println(q.dequeue()); //1 36 | System.out.println(q.dequeue()); //2 37 | } 38 | } -------------------------------------------------------------------------------- /03_Stacks_and_Queues/README.md: -------------------------------------------------------------------------------- 1 | # Stacks and Queues 2 | -------------------------------------------------------------------------------- /03_Stacks_and_Queues/Stack/Stack.java: -------------------------------------------------------------------------------- 1 | import java.io.*; 2 | import java.util.LinkedList; 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | public class Stack { 8 | LinkedList stack; 9 | 10 | public Stack() { 11 | stack = new LinkedList(); 12 | } 13 | 14 | public Boolean push(Integer data) { 15 | stack.addLast(data); 16 | return true; 17 | } 18 | 19 | // removes the last added element 20 | public Integer pop() { 21 | if(stack.isEmpty()) { 22 | // no data to pop 23 | return -1; 24 | } 25 | Integer ret = stack.removeLast(); 26 | return ret; 27 | } 28 | 29 | //show the items in stack 30 | public void display() { 31 | System.out.println(stack); 32 | } 33 | 34 | public static void main(String[] args) { 35 | Stack st = new Stack(); 36 | st.push(1); 37 | st.push(3); 38 | st.push(2); 39 | st.display(); 40 | System.out.println(st.pop()); // 2 41 | st.display(); 42 | System.out.println(st.pop()); // 3 43 | System.out.println(st.pop()); // 1 44 | System.out.println(st.pop()); // -1 45 | assert(st.pop() == 1); 46 | System.out.println("success.. "); 47 | } 48 | } -------------------------------------------------------------------------------- /03_Stacks_and_Queues/Stack/stack.py: -------------------------------------------------------------------------------- 1 | # should support 2 | # 1) PUSH - adding the element at the end of the list 3 | # 2) POP - removing and returning the element at the end of the list 4 | # 3) PEEK - displaying the element at the end of list 5 | class Stack(object): 6 | def __init__(self): 7 | self.container = [] 8 | 9 | #adding into the stack 10 | def push(self, item): 11 | self.container.append(item) 12 | 13 | #removing an element 14 | def pop(self): 15 | if(len(self.container) == 0): 16 | #stack is empty 17 | print "empty stack can not be poped" 18 | return '' 19 | return self.container.pop() 20 | 21 | # Showing the last added element 22 | def peek(self): 23 | if(len(self.container) == 0): 24 | #stack is empty 25 | print "empty stack can not be peeked" 26 | return '' 27 | return self.container[len(self.container) - 1] # return the last element from the list 28 | 29 | 30 | def display(self): 31 | print self.container 32 | 33 | def isEmpty(self): 34 | return len(self.container) == 0 35 | 36 | 37 | def main(): 38 | s = Stack() 39 | s.push(1) 40 | s.push(2) 41 | s.push(3) 42 | assert s.pop() == 3 43 | assert s.pop() == 2 44 | assert s.pop() == 1 45 | print "all is well :)" 46 | 47 | if __name__ == '__main__': 48 | main() 49 | 50 | -------------------------------------------------------------------------------- /03_Stacks_and_Queues/minElementInStack/README.md: -------------------------------------------------------------------------------- 1 | ## Minimum ELement in stack in O(1) 2 | 3 | ``` 4 | Find the minimum element in a stack in O(1) time 5 | 6 | ``` 7 | minStack contains the data structure for finding the min element in O(1) 8 | ``` 9 | time complexity for min element : O(1) 10 | space complexity : O(n) 11 | ``` 12 | -------------------------------------------------------------------------------- /03_Stacks_and_Queues/minElementInStack/Stack.py: -------------------------------------------------------------------------------- 1 | # should support 2 | # 1) PUSH - adding the element at the end of the list 3 | # 2) POP - removing and returning the element at the end of the list 4 | # 3) PEEK - displaying the element at the end of list 5 | class Stack(object): 6 | def __init__(self): 7 | self.container = [] 8 | 9 | #adding into the stack 10 | def push(self, item): 11 | self.container.append(item) 12 | 13 | #removing an element 14 | def pop(self): 15 | if(len(self.container) == 0): 16 | #stack is empty 17 | print "empty stack can not be poped" 18 | return '' 19 | return self.container.pop() 20 | 21 | # Showing the last added element 22 | def peek(self): 23 | if(len(self.container) == 0): 24 | #stack is empty 25 | print "empty stack can not be peeked" 26 | return '' 27 | return self.container[len(self.container) - 1] # return the last element from the list 28 | 29 | 30 | def display(self): 31 | print self.container 32 | 33 | def isEmpty(self): 34 | return len(self.container) == 0 35 | 36 | 37 | def main(): 38 | s = Stack() 39 | s.push(1) 40 | s.push(2) 41 | s.push(3) 42 | assert s.pop() == 3 43 | assert s.pop() == 2 44 | assert s.pop() == 1 45 | print "all is well :)" 46 | 47 | if __name__ == '__main__': 48 | main() 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /03_Stacks_and_Queues/minElementInStack/minStack.py: -------------------------------------------------------------------------------- 1 | import Stack as st 2 | 3 | # Idea : 4 | # use another stack to store the minimum elements 5 | 6 | class minStack(object): 7 | def __init__(self): 8 | self.minStack = st.Stack() 9 | self.stack = st.Stack() 10 | 11 | def push(self, item): 12 | # when the stack is empty 13 | if(self.stack.isEmpty()): 14 | self.stack.push(item) 15 | self.minStack.push(item) 16 | return 17 | else: 18 | self.stack.push(item) 19 | curMin = self.minStack.peek() 20 | # if curMin is greater than the new item add the new item as min 21 | # else again add curmin 22 | if(curMin > item): 23 | self.minStack.push(item) 24 | else: 25 | self.minStack.push(curMin) 26 | 27 | def pop(self): 28 | # remove the element from the minStack 29 | self.minStack.pop() 30 | return self.stack.pop() 31 | 32 | # takes O(1) since we just need to get the top element of stack for getting the min elements 33 | def min(self): 34 | #returns the current minimum 35 | return self.minStack.peek() 36 | 37 | 38 | def main(): 39 | print 'testing min stack' 40 | stack = minStack() 41 | stack.push(5) # [5] 42 | assert stack.min() == 5 43 | stack.push(4) # [5, 4] 44 | assert stack.min() == 4 45 | stack.push(8) # [5, 4, 8] 46 | assert stack.min() == 4 47 | stack.push(3) # [5, 4, 8, 3] 48 | assert stack.min() == 3 49 | stack.pop() 50 | assert stack.min() == 4 51 | print 'all is well :)' 52 | 53 | if __name__ == "__main__": 54 | main() -------------------------------------------------------------------------------- /04_Trees_and_Graphs/countTheLeaves/README.md: -------------------------------------------------------------------------------- 1 | Write a function to find the total number of `leaf nodes` in a binary tree. A node is described as a leaf node if it doesn't have any children. If there are no leaf nodes, return `0`. 2 | 3 | ``` 4 | Example: 5 | 1 6 | / \ 7 | 2 3 8 | / \ / \ 9 | 4 5 6 7 10 | / \ 11 | 8 9 12 | ==> no. of leaves = 5 13 | ``` 14 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/countTheLeaves/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | 3 | public static int numberOfLeaves(TreeNode root) { 4 | if (root == null) return 0; 5 | else if (root.left == null && root.right == null) { 6 | return 1; 7 | } 8 | else { 9 | return numberOfLeaves(root.left) + numberOfLeaves(root.right); 10 | } 11 | } 12 | 13 | class TreeNode { 14 | int data; 15 | TreeNode left; 16 | TreeNode right; 17 | TreeNode(int data, TreeNode left, TreeNode right) { 18 | this.data = data; 19 | this.left = left; 20 | this.right = right; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/hasPathSum/README.md: -------------------------------------------------------------------------------- 1 | **Given a binary tree and a sum, return true if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. Return false if no such path can be found.** 2 | 3 | We'll define a "root-to-leaf path" to be a sequence of nodes in a tree starting with the root node and proceeding downward to a leaf (a node with no children). We'll say that an empty tree contains no root-to-leaf paths. So for example, the following tree has exactly four root-to-leaf paths: 4 | 5 | ``` 6 | 5 7 | / \ 8 | 4 8 9 | / / \ 10 | 11 13 4 11 | / \ \ 12 | 7 2 1 13 | 14 | Root-to-leaf paths: 15 | path 1: 5 4 11 7 16 | path 2: 5 4 11 2 17 | path 3: 5 8 13 18 | path 4: 5 8 4 1 19 | 20 | ``` 21 | 22 | For this problem, we will be concerned with the sum of the values of such a path -- for example, the sum of the values on the 5-4-11-7 path is 5 + 4 + 11 + 7 = 27. 23 | 24 | ## Solution 25 | subtract the node value from the sum when recurring down, and check to see if the sum is 0 when you run out of tree. 26 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/hasPathSum/Solution.java: -------------------------------------------------------------------------------- 1 | 2 | public class Solution { 3 | boolean hasPathSum(TreeNode node, int sum){ 4 | if (node == null) { 5 | return (sum == 0); 6 | } 7 | // check both the subtrees 8 | int remainingSum = sum - node.data; 9 | return ( hasPathSum(node.left, remainingSum) || 10 | hasPathSum(node.right, remainingSum) ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/invert-binary-tree/README.md: -------------------------------------------------------------------------------- 1 | # Invert Binary Tree 2 | 3 | ![Difficulty-Easy](https://img.shields.io/badge/Difficulty-Easy-green) 4 | 5 | Invert a binary tree. 6 | 7 | ## Example: 8 | 9 | ``` 10 | Input: 11 | 12 | 4 13 | / \ 14 | 2 7 15 | / \ / \ 16 | 1 3 6 9 17 | 18 | Output: 19 | 20 | 4 21 | / \ 22 | 7 2 23 | / \ / \ 24 | 9 6 3 1 25 | ``` 26 | 27 | ## Complexity Analysis: 28 | 29 | - **Time complexity** : `O(n)`. Since each node in the tree is visited only once, the time complexity is `O(n)`, where `n` is the number of nodes in the tree. We cannot do better than that, since at the very least we have to visit each node to invert it. 30 | 31 | - **Space complexity** : `O(h) where h is height, or O(log(n)) - best, o(n) worst`. `O(h)` function calls will be placed on the stack in the worst case, where `h` is the height of the tree. Because `h ∈ O(n)`, the space complexity is `O(n)` (worst case). The best case is for a completely balanced tree. The worst case is for an unbalanced tree. 32 | 33 | #### [LeetCode link](https://leetcode.com/problems/invert-binary-tree/) 34 | 35 | > Look at solution 2 in leetcode for a queue based approach with the same time and space complexities -------------------------------------------------------------------------------- /04_Trees_and_Graphs/invert-binary-tree/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @return {TreeNode} 11 | */ 12 | var invertTree = function(root) { 13 | if (!root) return root 14 | const left = invertTree(root.left) 15 | const right = invertTree(root.right) 16 | root.left = right 17 | root.right = left 18 | return root 19 | }; -------------------------------------------------------------------------------- /04_Trees_and_Graphs/isBST/README.md: -------------------------------------------------------------------------------- 1 | # Validate Binary Search Tree 2 | 3 | ![Difficulty-Medium](https://img.shields.io/badge/Difficulty-Medium-yellow) 4 | 5 | Given a binary tree, determine if it is a valid binary search tree (BST). 6 | 7 | Assume a BST is defined as follows: 8 | 9 | The left subtree of a node contains only nodes with keys less than the node's key. 10 | The right subtree of a node contains only nodes with keys greater than the node's key. 11 | Both the left and right subtrees must also be binary search trees. 12 | 13 | 14 | ## Example 1: 15 | 16 | ``` 17 | 2 18 | / \ 19 | 1 3 20 | 21 | Input: [2,1,3] 22 | Output: true 23 | ``` 24 | 25 | ## Example 2: 26 | 27 | ``` 28 | 5 29 | / \ 30 | 1 4 31 | / \ 32 | 3 6 33 | 34 | Input: [5,1,4,null,null,3,6] 35 | Output: false 36 | Explanation: The root node's value is 5 but its right child's value is 4. 37 | ``` 38 | 39 | ## Complexity Analysis (recursion based solution): 40 | 41 | - **Time complexity** : `O(n)`. We visit each node in the tree exactly once. 42 | 43 | - **Space complexity** : `O(log(n)) - best, o(n) worst`. The best case is for a completely balanced tree. The worst case is for an unbalanced tree. The space is to keep a recursion stack. 44 | 45 | #### [LeetCode link](https://leetcode.com/problems/validate-binary-search-tree/) -------------------------------------------------------------------------------- /04_Trees_and_Graphs/isBST/Solution.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public static boolean isBST(TreeNode root) { 3 | return isBSTRecur(root, Integer.MIN_VALUE, Integer.MAX_VALUE) ); 4 | } 5 | public static boolean isBSTRecur(TreeNode node, int min, int max) { 6 | if (node == null) return true; 7 | // check if min/max constraint is violated 8 | if (!(node.data > min && node.data < max)) return false; 9 | // recursively check for subtrees 10 | return isBSTRecur(node.left, min, node.data) && 11 | isBSTRecur(node.right, node.data, max); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/isBST/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @return {boolean} 11 | */ 12 | 13 | /* Recursion based solution */ 14 | var isValid = (node, min, max) => { 15 | if (!node) return true 16 | // if constraint is not satisified return false 17 | if (!(node.val > min && node.val < max)) return false; 18 | return isValid(node.left, min, node.val) && isValid(node.right, node.val, max) 19 | } 20 | 21 | var isValidBST = function(root) { 22 | return isValid(root, Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER) 23 | }; 24 | 25 | /* 26 | NOTE: in JS NUMBER.MIN_VALUE is the value closest to 0, not the negative minimum 27 | */ -------------------------------------------------------------------------------- /04_Trees_and_Graphs/isBalanced/README.md: -------------------------------------------------------------------------------- 1 | **Determine if a tree is balanced** 2 | 3 | ## Solution (Recursive) 4 | 5 | Recursively for each node check, 6 | - if the left subtree is balanced 7 | - if the right subtree is balanced 8 | - if the difference between the height of left and right subtrees is not greater than 1 9 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/isBalanced/Solution.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | 3 | public static boolean isBalanced(TreeNode root) { 4 | return getHeight(root) != -1; 5 | } 6 | 7 | // recursive function to determine the height of a tree, returns -1 if its a unbalanced tree 8 | private static int getHeight(TreeNode node) { 9 | if(node == null) return 0; 10 | // check if left subtree is balanced 11 | int leftHeight = getHeight(node.left); 12 | if(leftHeight == -1) return -1; 13 | // check if right subtree is balanced 14 | int rightHeight = getHeight(node.right); 15 | if (rightHeight == -1) return -1; 16 | // if the difference between the height of left and right subtrees is not greater than 1 17 | int difference = leftHeight - rightHeight; 18 | if (Math.abs(difference) > 1) return -1; 19 | // return the height of this subtree 20 | return Math.max(leftHeight, rightHeight); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/levelOrderTraversal/README.md: -------------------------------------------------------------------------------- 1 | **Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).** 2 | 3 | ## Solution 4 | - Use a level limiter END to determine end of level. 5 | - Use queue to add each element of tree. 6 | - Whenever END is encountered it marks the end of current level 7 | - Solution returns `List>`, can be modified to print level wise. 8 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/levelOrderTraversal/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | public List> levelOrder(TreeNode root) { 3 | List> result = new LinkedList>(); 4 | if(root == null) return result; 5 | TreeNode END = new TreeNode(-1); // marks the end of level 6 | LinkedList level = new LinkedList(); 7 | LinkedList q = new LinkedList(); 8 | q.add(root); 9 | q.add(END); 10 | while(!q.isEmpty()) { 11 | TreeNode cur = q.removeFirst(); 12 | if(cur == END) { // current level is done 13 | result.add(level); 14 | level = new LinkedList(); 15 | if(!q.isEmpty()) // to avoid infinite add of END 16 | q.add(END); 17 | continue; 18 | } 19 | level.add(cur.val); 20 | if(cur.left != null) { 21 | q.add(cur.left); 22 | } 23 | if(cur.right != null) { 24 | q.add(cur.right); 25 | } 26 | } 27 | return result; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/maximum-depth-of-binary-tree/README.md: -------------------------------------------------------------------------------- 1 | # Maximum Depth of Binary Tree 2 | 3 | ![Difficulty-Easy](https://img.shields.io/badge/Difficulty-Easy-green) 4 | 5 | Given a binary tree, find its maximum depth. 6 | 7 | The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 8 | 9 | Note: A leaf is a node with no children. 10 | 11 | ## Example: 12 | 13 | ``` 14 | Given binary tree [3,9,20,null,null,15,7], 15 | 16 | 3 17 | / \ 18 | 9 20 19 | / \ 20 | 15 7 21 | return its depth = 3. 22 | ``` 23 | 24 | ## Complexity Analysis: 25 | 26 | - **Time complexity** : `O(n)`. We visit each node in the tree exactly once. 27 | 28 | - **Space complexity** : `O(log(n)) - best, o(n) worst`. The best case is for a completely balanced tree. The worst case is for an unbalanced tree. The space is to keep a recursion stack. 29 | 30 | #### [LeetCode link](https://leetcode.com/problems/maximum-depth-of-binary-tree/) -------------------------------------------------------------------------------- /04_Trees_and_Graphs/numberOfIslands/README.md: -------------------------------------------------------------------------------- 1 | **Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.** 2 | 3 | ## Solution (Recursive) 4 | - Start at the first land vertex 5 | - DFS and mark all the parts of the single island 6 | - DFS terminates after marking all the regions of the current island. 7 | - increment the island count and go to next land portion. 8 | - go to step 2 and repeat until all the land regions are discovered. 9 | - You can also visited boolean array as flag to mark the visited land regions. 10 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/numberOfIslands/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | public int numIslands(char[][] grid) { 3 | int islands = 0; 4 | int l = grid.length; 5 | if(l == 0) return islands; 6 | int b = grid[0].length; 7 | if(b == 0) return islands; 8 | 9 | for(int i = 0; i < l; i++) { 10 | for(int j = 0; j < b; j++) { 11 | if(grid[i][j] == '1') { 12 | islands++; 13 | dfs(i, j, l, b, grid); // dfs marks individual island groups 14 | } 15 | } 16 | } 17 | return islands; 18 | } 19 | 20 | private void dfs(int i, int j, int l, int b, char[][] grid) { 21 | if(i < 0 || j < 0 || i >= l || j >= b || grid[i][j] != '1') return; 22 | grid[i][j] = '0'; // mark as complete ( you can also use visited ) 23 | dfs(i-1, j, l, b, grid); // check top 24 | dfs(i+1, j, l, b, grid); // check bottom 25 | dfs(i, j-1, l, b, grid); // check left 26 | dfs(i, j+1, l, b, grid); // check right 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/pathSum2/README.md: -------------------------------------------------------------------------------- 1 | 2 | **Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum.** 3 | 4 | [LeetCode Link](https://leetcode.com/problems/path-sum-ii/) 5 | 6 | Note: A leaf is a node with no children. 7 | 8 | Example: 9 | 10 | ``` 11 | Given the below binary tree and sum = 22, 12 | 13 | 5 14 | / \ 15 | 4 8 16 | / / \ 17 | 11 13 4 18 | / \ / \ 19 | 7 2 5 1 20 | Return: 21 | 22 | [ 23 | [5,4,11,2], 24 | [5,8,4,5] 25 | ] 26 | ``` 27 | 28 | ## Solution 29 | 30 | Subtract the node value from the sum when recurring down, and check to see if the sum is the node value when you reach the leaf. -------------------------------------------------------------------------------- /04_Trees_and_Graphs/pathSum2/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} root 10 | * @param {number} sum 11 | * @return {number[][]} 12 | */ 13 | var pathSum = function(root, sum) { 14 | let allPaths = []; 15 | recur(root, sum, [], allPaths); 16 | return allPaths; 17 | }; 18 | 19 | const recur = (node, sum, parents, allPaths) => { 20 | if (node === null) return; 21 | // if its a leaf and if the sum we need to check is equivalent to node's value then bingo we have a path 22 | if (node.left === null && node.right === null && node.val === sum) { 23 | allPaths.push([...parents, node.val]); 24 | } 25 | // the child of this node must know that this is its parent 26 | parents.push(node.val); 27 | // subtract the current sum with the root's value, so that the child can check 28 | recur(node.left, sum - node.val, parents, allPaths); 29 | recur(node.right, sum - node.val, parents, allPaths); 30 | // we need to pop the array with this node as the parent, so that while reucrring we dont hit invalid parents 31 | parents.pop(); 32 | } -------------------------------------------------------------------------------- /04_Trees_and_Graphs/projectDependencies/README.md: -------------------------------------------------------------------------------- 1 | You are given a list of projects and a list of dependencies. All of a project's dependencies must be built before the project is. Find a build order that will allow the projects to be built. If there is no valid build order return an error. 2 | 3 | ## Example 4 | ``` 5 | projects: a, b, c, d, e, f 6 | dependencies: (f, b), (f, c), (f, a), (b, e), (a, e), (d, e) 7 | ``` 8 | 9 | ## Solution 10 | 11 | Use **topological sort**, 12 | - It is the reverse of DFS finishing times 13 | 14 | To find invalid build error, 15 | - Find if the graph has a backedge while doing DFS. 16 | 17 | ## Result 18 | ``` 19 | [f, d, g, c, b, a, e] 20 | ``` 21 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/sameLevel/README.md: -------------------------------------------------------------------------------- 1 | **Check if all the leaves are at the same level in a binary tree** 2 | 3 | ## Solution (Recursive) 4 | - Use a static variable which will be set with the level of leaf node, when we encounter a leaf node for the first time. 5 | - Every time we see a leaf node we check whether the level of this leaf node is same as the one set in the static variable 6 | - If no, return false 7 | - else continue till all the other leaf nodes are seen. 8 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/sameLevel/Solution.java: -------------------------------------------------------------------------------- 1 | class Solution { 2 | public static boolean sameLevel(TreeNode root) { 3 | return sameLevelRecur(root, 0); // the root is at level 0 4 | } 5 | 6 | public static boolean sameLevelRecur(TreeNode node, int curLevel) { 7 | static int firstLeafLevel = -1; // -1 is just to find if it is not set yet 8 | // if its a leaf 9 | if(node.left == null && node.right == null) { 10 | // encountered the first leaf 11 | if (firstLeafLevel == -1) { 12 | firstLeafLevel = curLevel; 13 | return true; 14 | } 15 | return (curLevel == firstLeafLevel); 16 | } 17 | // recurse for the subtrees 18 | int nextLevel = curLevel+1; 19 | return sameLevelRecur(node.left, nextLevel) && 20 | sameLevelRecur(node.right, nextLevel) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/sameTree/README.md: -------------------------------------------------------------------------------- 1 | # Same Tree 2 | 3 | ![Difficulty-Easy](https://img.shields.io/badge/Difficulty-Easy-green) 4 | 5 | Given two binary trees, write a function to check if they are the same or not. 6 | 7 | Two binary trees are considered the same if they are structurally identical and the nodes have the same value. 8 | 9 | ## Example 1: 10 | 11 | ``` 12 | Input: 1 1 13 | / \ / \ 14 | 2 3 2 3 15 | 16 | [1,2,3], [1,2,3] 17 | 18 | Output: true 19 | ``` 20 | 21 | ## Example 2: 22 | 23 | ``` 24 | Input: 1 1 25 | / \ 26 | 2 2 27 | 28 | [1,2], [1,null,2] 29 | 30 | Output: false 31 | ``` 32 | 33 | ## Example 3: 34 | 35 | ``` 36 | Input: 1 1 37 | / \ / \ 38 | 2 1 1 2 39 | 40 | [1,2,1], [1,1,2] 41 | 42 | Output: false 43 | ``` 44 | 45 | ## Complexity Analysis: 46 | 47 | - **Time complexity** : `O(2n) = O(n)`. where `n` is a number of nodes in a tree. We visit each node in both trees exactly once. 48 | 49 | - **Space complexity** : `O(log(n)) - best, o(n) worst`. The best case is two completely balanced trees. The worst case is two completely unbalanced trees, to keep a recursion stack. 50 | 51 | #### [LeetCode link](https://leetcode.com/problems/same-tree/) -------------------------------------------------------------------------------- /04_Trees_and_Graphs/sameTree/Solution.java: -------------------------------------------------------------------------------- 1 | public class Solution { 2 | public static boolean sameTree(TreeNode tree1, TreeNode tree2) { 3 | // both are empty 4 | if(tree1 == null && tree2 == null) { 5 | return true; 6 | } 7 | // both are non empty, compare their data and recurse 8 | else if(tree != null && tree2 != null) { 9 | return tree1.data == tree2.data && 10 | sameTree(tree1.left, tree2.left) && 11 | sameTree(tree1.right, tree2.right); 12 | } 13 | // one is empty, other is not 14 | else { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /04_Trees_and_Graphs/sameTree/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} p 10 | * @param {TreeNode} q 11 | * @return {boolean} 12 | */ 13 | var isSameTree = function(p, q) { 14 | if (!p || !q) { 15 | return p === q 16 | } 17 | return p.val === q.val && isSameTree(p.left, q.left) && isSameTree(p.right, q.right) 18 | }; -------------------------------------------------------------------------------- /04_Trees_and_Graphs/subtree-of-another-tree/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Definition for a binary tree node. 3 | * function TreeNode(val) { 4 | * this.val = val; 5 | * this.left = this.right = null; 6 | * } 7 | */ 8 | /** 9 | * @param {TreeNode} s 10 | * @param {TreeNode} t 11 | * @return {boolean} 12 | */ 13 | var isSameTree = (r, t) => { 14 | if (!r || !t) return r === t 15 | return r.val === t.val && isSameTree(r.left, t.left) && isSameTree(r.right, t.right) 16 | } 17 | 18 | var isSubtree = function(s, t) { 19 | return s !== null && (isSameTree(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t)) 20 | }; -------------------------------------------------------------------------------- /05_Bit_Manipulation/AddBinary/README.md: -------------------------------------------------------------------------------- 1 | 2 | [LeetCode Link](https://leetcode.com/problems/add-binary/) 3 | 4 | 5 | **Given two binary strings, return their sum (also a binary string)** 6 | 7 | The input strings are both non-empty and contains only characters 1 or 0. 8 | 9 | Example: 10 | 11 | ``` 12 | Example 1: 13 | 14 | Input: a = "11", b = "1" 15 | Output: "100" 16 | 17 | Example 2: 18 | 19 | Input: a = "1010", b = "1011" 20 | Output: "10101" 21 | ] 22 | ``` 23 | 24 | ## Solution 25 | 26 | Remember the binary addition rules shown below, and remember the carry over in the code during each addition 27 | 28 | ``` 29 | 0 + 0 = 0 30 | 0 + 1 = 1 31 | 1 + 0 = 1 32 | 1 + 1 = 10 33 | 1 + 1 + 1 = 10 + 1 = 11 34 | ``` 35 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/AddBinary/solution.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} a 3 | * @param {string} b 4 | * @return {string} 5 | */ 6 | var addBinary = function(a, b) { 7 | // http://web.math.princeton.edu/math_alive/Crypto/Lab1/BinAddEx2.html 8 | // http://www.binarymath.info/binary-addition.php 9 | /* 10 | 0 + 0 = 0 11 | 0 + 1 = 1 12 | 1 + 0 = 1 13 | 1 + 1 = 10 14 | 1 + 1 + 1 = 10 + 1 = 11 15 | */ 16 | let ans = "" 17 | let aIndex = a.length - 1 18 | let bIndex = b.length - 1 19 | let carry = null 20 | while(aIndex >= 0 || bIndex >= 0 || carry !== null) { 21 | let ansThisLoop = 0 22 | if (aIndex >= 0) { 23 | ansThisLoop = a.charAt(aIndex) - '0' 24 | } 25 | if (bIndex >= 0) { 26 | ansThisLoop = ansThisLoop + (b.charAt(bIndex) - '0') 27 | } 28 | if (carry !== null) { 29 | ansThisLoop = ansThisLoop + carry 30 | } 31 | // the binary conversion happens here 32 | if (ansThisLoop === 2) { 33 | carry = 1 34 | ansThisLoop = 0 35 | } else if (ansThisLoop === 3) { 36 | carry = 1 37 | ansThisLoop = 1 38 | } else { 39 | carry = null 40 | } 41 | ans = '' + ansThisLoop + ans 42 | aIndex-- 43 | bIndex-- 44 | } 45 | return ans 46 | }; 47 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Basics/README.md: -------------------------------------------------------------------------------- 1 | # How to set, clear, toggle and check a bit ? 2 | See the comments in `main.cpp` to understand how the routines work. 3 | 4 | [Refer](http://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit-in-c-c) for a more detailed discussion. 5 | 6 | ## C++ STL natively supports this 7 | ```c 8 | #include 9 | #include 10 | 11 | int main() 12 | { 13 | std::bitset<5> x; 14 | 15 | x[1] = 1; 16 | x[2] = 0; 17 | // Note x[0-4] valid 18 | 19 | std::cout << x << std::endl; 20 | } 21 | ``` 22 | ```c 23 | [Alpha:] > ./a.out 24 | 00010 25 | ``` 26 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Basics/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void setBit(int &number, const int &i) 5 | { 6 | number |= 1U << i; 7 | } 8 | 9 | void clearBit(int &number, const int &i) 10 | { 11 | number &= ~( 1U << i ); 12 | } 13 | 14 | void toggleBit(int &number, const int &i) 15 | { 16 | number ^= 1U << i; 17 | } 18 | 19 | void checkBit(int &number, const int &i, int &bit) 20 | { 21 | bit = (number >> i) & 1U; 22 | } 23 | 24 | int main() 25 | { 26 | int num = 131; // 10000011 27 | setBit( num, 4 ); // 10000011 | 00010000 = 10010011 28 | assert( num == 147); // 10010011 = 147 29 | // num is now 147 30 | clearBit( num, 4); // 10010011 & 11101111 = 10000011 31 | assert( num == 131 ); // 10000011 = 131 32 | // num is now 131 33 | toggleBit( num, 1 ); // 10000011 ^ 00000010 = 10000001 34 | assert( num == 129 ); // 10000001 = 129 35 | int bit = 0; 36 | checkBit( num, 7, bit); // (10000001 >> 7) & 1 = 00000001 & 000000001 37 | assert( bit == 1); // 000000001 = 1 38 | std::cout << "All asserts passed" << std::endl; 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/CountThe1-s/README.md: -------------------------------------------------------------------------------- 1 | ##How Does it Work 2 | 3 | ###Method 1: 4 | Step 1: 5 | ``` 6 | 1 is subtracted from the number 7 | ``` 8 | 9 | Step 2: 10 | ``` 11 | perform x AND x-1 to remove the last 1. See the below diagram 12 | count variable takes count of the number of 1 in the variable 13 | ``` 14 | |variable| binary value| 15 | |-------|------| 16 | |x| 00101101110**1**0000| 17 | |x-1| 00101101110**01111**| 18 | |x & (x-1)|00101101110**00000**| 19 | 20 | Step 3: 21 | ``` 22 | output the count 23 | ``` 24 | #### Performance 25 | Proportinal to the number of bits in the word. Takes O(n) time in worst case if all the bits are one. 26 | 27 | ### Method 2: 28 | #### Strategy: 29 | Parallel divide- and-conquer 30 | 31 | ####Steps: 32 | ![Count 1](https://cloud.githubusercontent.com/assets/3127498/5535327/2e42078c-8a4a-11e4-8d44-c73668eb3899.png) 33 | 34 | ####Performance: 35 | Takes O(lg n) times where n is the word Length. 36 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/CountThe1-s/main.swift: -------------------------------------------------------------------------------- 1 | /*COUNT the number of 1's in the number */ 2 | /* 3 | @param n:Int value whose 1's has to be counted 4 | @return Int number of 1's in the n 5 | */ 6 | 7 | //Method 1: 8 | func count1(var n:Int) -> Int { //var is added to make it a variable from constant(let) 9 | var b:Int 10 | for b = 0; n != 0; ++b { 11 | n = n & (n-1) 12 | } 13 | return b 14 | } 15 | count1(7) //3 16 | 17 | //Method 2 18 | func count1DivideAndConquer(var x:Int) -> Int { 19 | var B5 = ~((-1) << 32) //mask of all 32 bits 20 | var B4 = B5 ^ (B5 << 16); 21 | var B3 = B4 ^ (B4 << 8); 22 | var B2 = B3 ^ (B3 << 4); 23 | var B1 = B2 ^ (B2 << 2); 24 | var B0 = B1 ^ (B1 << 1); 25 | x = ((x >> 1) & B0) + (x & B0); 26 | x = ((x >> 2) & B1) + (x & B1); x = ((x >> 4) + x) & B2; 27 | x = ((x >> 8) + x) & B3; 28 | x = ((x >> 16) + x) & B4; 29 | x = ((x >> 32) + x) & B5; 30 | return x 31 | } 32 | 33 | count1DivideAndConquer(7) //3 34 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Merge-Two-Sorted-Arrays/README.md: -------------------------------------------------------------------------------- 1 | # Merge two sorted arrays with bitHack 2 | 3 | See the comments in main.cpp for explanation 4 | 5 | ## Note 6 | 7 | ```c 8 | ptr++; // Pointer moves to the next int position (as if it was an array) 9 | *ptr++; // Pointer moves to the next int position (as if it was an array). But returns the old content 10 | ``` 11 | [Read more at stackoverflow ](http://stackoverflow.com/questions/8208021/how-to-increment-a-pointer-address-and-pointers-value) 12 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Merge-Two-Sorted-Arrays/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | static void merge (int *C, int *A, int *B, size_t na, size_t nb) { 6 | while (na > 0 && nb > 0) { 7 | if (*A <= *B) { 8 | *C++ = *A++; na--; 9 | } 10 | else { 11 | *C++ = *B++; nb--; 12 | } 13 | } 14 | while (na > 0) { 15 | *C++ = *A++; 16 | na--; 17 | } 18 | while (nb > 0) { 19 | *C++ = *B++; 20 | nb--; 21 | } 22 | } 23 | 24 | static void merge_BitHack (int *C, int *A, int *B, size_t na, size_t nb) { 25 | while (na > 0 && nb > 0) { 26 | int cmp = (*A <= *B); 27 | int min = *B ^ ((*B ^ *A) & (-cmp)); // the 'minimum of two numbers' bitHack 28 | *C++ = min; 29 | A += cmp; na -= cmp; // if A is the minimum, do A++ and na-­‐; 30 | B += !cmp; nb -= !cmp; // if B is the minimum, do B++ and nb-­‐; 31 | } 32 | while (na > 0) { 33 | *C++ = *A++; 34 | na--; 35 | } 36 | while (nb > 0) 37 | { 38 | *C++ = *B++; 39 | nb--; 40 | } 41 | } 42 | 43 | int equalArrays ( int *needed, int *existing, size_t size) { 44 | for (int i = 0; i < size; i++){ 45 | if(needed[i] != existing[i]) return 0; 46 | } 47 | return 1; 48 | } 49 | 50 | void printArray( int *A, size_t size) { 51 | for(int i = 0; i < size; i++) { 52 | printf("%d ", A[i]); 53 | } 54 | printf("\n"); 55 | } 56 | 57 | int main ( void ) { 58 | int A[4] = { 3, 12, 19, 46 }; 59 | int B[4] = { 4, 14, 21, 23 }; 60 | int C[8]; 61 | int required[8] = { 3, 4, 12, 14, 19, 21, 23, 46}; 62 | merge_BitHack ( C, A, B, sizeof(A)/sizeof(A[0]), sizeof(B)/sizeof(B[0]) ); 63 | printArray( C, sizeof(C)/sizeof(C[0]) ); 64 | assert ( equalArrays( required , C, sizeof(C)/sizeof(C[0])) ); 65 | } 66 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Minimum-Of-Two-Integers/README.md: -------------------------------------------------------------------------------- 1 | ```c 2 | minimum = y ^ ((x ^ y) & -(x < y)); 3 | ``` 4 | 5 | ## How does it work ? 6 | 7 | When `x < y == 1`, 8 | ```c 9 | then −(x < y) = −1; // 11111111 ( 2's complement representation ) 10 | so minimum = y ^ ( (x ^ y) & 11111111 ) 11 | => minimum = y ^ ( x ^ y ) 12 | => minimum = x 13 | ``` 14 | When `x < y == 0`, 15 | ```c 16 | then −(x < y) = −0; // 00000000 17 | so minimum = y ^ ( (x ^ y) & 0 ) 18 | => minimum = y ^ 0 19 | => minimum = y 20 | ``` 21 | ## Performance without Bit-Hack 22 | ```c 23 | minimum = (x < y) ? x : y; 24 | ``` 25 | A mispredicted branch empties the processor pipeline 26 | 27 | * ~16 cycles on Intel Core i7’s. 28 | 29 | The compiler might be smart enough to avoid the 30 | unpredictable branch, but maybe not. 31 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Minimum-Of-Two-Integers/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void FindMin_Naive(int &result, const int &x, const int &y) 5 | { 6 | result = (x < y) ? x : y; 7 | } 8 | 9 | void FindMin_BitHack(int &result, const int &x, const int &y) 10 | { 11 | result = y ^ ((x ^ y) & -(x < y)); 12 | } 13 | 14 | int main() 15 | { 16 | int result = 0; 17 | FindMin_Naive( result, 147, 274 ); 18 | assert( result == 147 ); 19 | result = 0; 20 | FindMin_BitHack( result, 147, 274 ); 21 | assert( result == 147 ); 22 | std::cout << "All asserts passed" << std::endl; 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Minimum-Of-Two-Integers/main.swift: -------------------------------------------------------------------------------- 1 | /* function which returns the minimum element 2 | @param x:Int 3 | @param y:Int 4 | @return Int the mininmum of x,y 5 | */ 6 | 7 | func findMin(x:Int, y:Int) -> Int { 8 | return (y ^ ((x ^ y) & -((x < y) ?1 :0))) 9 | } 10 | 11 | findMin(10, 15) //tested in playground 12 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Modular-Addition/README.md: -------------------------------------------------------------------------------- 1 | # Compute (x + y) mod n, assuming that 0 ≤ x < n and 0 ≤ y < n. 2 | 3 | ## Naive 4 | **Divide is expensive, unless by a power of 2.** 5 | ```c 6 | result = (x + y) % n; 7 | ``` 8 | ## Optimal 9 | **Unpredictable branch is expensive** 10 | ```c 11 | z = x + y; 12 | result = (z < n) ? z : z-n; 13 | ``` 14 | ## With Bithack 15 | ```c 16 | z = x + y; 17 | result = ( z - (n & -(z >= n)) ); 18 | ``` 19 | **Same trick as the `Minimum of 2 integers`** 20 | ## How does it work ? 21 | 22 | When `z >= n == 1`, 23 | ```c 24 | then −(z >= n) = −1; // 11111111 ( 2's complement representation ) 25 | so result = z - ( n & 11111111 ) 26 | => result = z - n 27 | ``` 28 | When `z >= n == 0`, 29 | ```c 30 | then −(z >= n) = −0; // 00000000 31 | so result = z - ( n & 0 ) 32 | => minimum = y ^ 0 33 | => result = z 34 | ``` 35 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Modular-Addition/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int modAdd_Naive(const int &x, const int &y, const int &n) 5 | { 6 | return ( (x + y) % n ); // Divide is expensive, unless by a power of 2. 7 | } 8 | 9 | int modAdd_Optimal(const int &x, const int &y, const int &n) 10 | { 11 | int z = x + y; 12 | return ( (z < n) ? z : (z-n) ); // Unpredictable branch is expensive 13 | } 14 | 15 | int modAdd_BitHack(const int &x, const int &y, const int &n) 16 | { 17 | int z = x + y; 18 | return ( z - (n & -(z >= n)) ); // same trick as minimum 19 | } 20 | 21 | int main() 22 | { 23 | int a = 147, b = 45, n = 7000; 24 | assert( modAdd_Naive( a, b, n ) == modAdd_Optimal( a, b, n ) ); 25 | int A = 432, B = 2000, N = 100000; 26 | assert( modAdd_Naive( A, B, N ) == modAdd_Optimal( A, B, N ) ); 27 | std::cout << "All asserts passed" << std::endl; 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Modular-Addition/main.swift: -------------------------------------------------------------------------------- 1 | /* 2 | Compute (x+y)mod n 3 | Assumption x,y < n 4 | 5 | @param x:Int 6 | @param y:Int 7 | @param n:Int Modulus number 8 | @return Int Modulus of the sum of x,y 9 | */ 10 | 11 | func modAddition( x:Int, y:Int, n:Int) -> Int { 12 | var z = x + y 13 | return (z - (n & -((z >= n) ?1 :0))) 14 | } 15 | 16 | modAddition(5, 4, 6) //result 9 % 6 = 3 17 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/NextPowerof2/NextPowerOf2.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | 3 | /* calculate the next power of 2 for the number (if it is of 32 bits 4 | @param n:Int 5 | @return Int next power of 2 6 | */ 7 | 8 | func nextPowerOf2(var n:Int32) -> Int32 { //O(lg n) 9 | --n //cornor cases of power of 2 10 | n = n | n >> 1 11 | n = n | n >> 2 12 | n = n | n >> 4 13 | n = n | n >> 8 14 | n = n | n >> 16 15 | ++n 16 | return n 17 | } 18 | 19 | nextPowerOf2(16) 20 | 21 | func nextPowerof2_shiftingMethod(var n:Int) -> Int { //O(lg n) 22 | //base case 23 | if((n != 1) && (n & (n-1) == 0)) { //Any power of 2 minus 1 is all ones so the bitwise & result in 0 if power of 2 24 | return n 25 | } 26 | var count = 0; 27 | while n != 0 { 28 | count++ 29 | n = n >> 1 30 | } 31 | return (1 << count) 32 | } 33 | 34 | nextPowerof2_shiftingMethod(12345) -------------------------------------------------------------------------------- /05_Bit_Manipulation/NextPowerof2/ReadME.md: -------------------------------------------------------------------------------- 1 | ## Next Power of 2 for the given number 2 | 3 | ``` 4 | Write a function that, for a given no n, finds a number p which is greater than or equal to n and is a power of 2. 5 | ``` 6 | 7 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/README.md: -------------------------------------------------------------------------------- 1 | # Bit Manipulation 2 | 3 | ## Problems 4 | 5 | - Given two binary strings, return their sum (also a binary string) - **[AddBinary](AddBinary)** 6 | 7 | 8 | ## Reference 9 | 10 | * ### [Absolute Beginner's Guide to Bit Shifting (Java specific) ](http://stackoverflow.com/questions/141525/absolute-beginners-guide-to-bit-shifting) 11 | 12 | * ### [MIT 6.172 2010 ocw slides ](http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-172-performance-engineering-of-software-systems-fall-2010/video-lectures/lecture-2-bit-hacks/MIT6_172F10_lec02.pdf) 13 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Subsets/README.md: -------------------------------------------------------------------------------- 1 | ## Question 2 | 3 | ```` 4 | Given a set of distinct integers, S, return all possible subsets. 5 | 6 | Note: 7 | Elements in a subset must be in non-descending order. 8 | The solution set must not contain duplicate subsets. 9 | For example, 10 | If S = [1,2,3], a solution is: 11 | [ 12 | [3], 13 | [1], 14 | [2], 15 | [1,2,3], 16 | [1,3], 17 | [2,3], 18 | [1,2], 19 | [] 20 | ] 21 | ``` 22 | 23 | #### Algorithm: 24 | BitManipulation 25 | 26 | ``` 27 | if the length of array is 3. binary value of 0 to 2^3-1 contain all posible combinations 28 | 1 1 29 | 2 10 30 | 3 11 31 | 4 100 32 | 5 101 33 | 6 110 34 | 7 111 35 | ``` 36 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Subsets/Subsets.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Given a set of distinct integers, S, return all possible subsets. 3 | * 4 | * Note: Elements in a subset must be in non-descending order. The solution set 5 | * must not contain duplicate subsets. For example, If S = [1,2,3], a solution 6 | * is: 7 | * 8 | * [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ] 9 | * algorithm: 10 | * if number of elements is 2 11 | * 2 ^ 2 - 1 is 3 12 | * 0 - 0 13 | * 1 - 1 14 | * 2 - 10 15 | * 3 - 11 16 | * 17 | * here we can see a pattern in the binary representation which represents the combinations 18 | * 0 - 0 - [] 19 | * 1 - 1 - [1] 20 | * 2 - 10 - [2] 21 | * 3 - 11 - [1, 2] 22 | */ 23 | 24 | 25 | import java.util.*; 26 | import java.lang.*; 27 | import java.io.*; 28 | 29 | /* Name of the class has to be "Main" only if the class is public. */ 30 | class Subsets 31 | { 32 | public ArrayList> subsets(int[] S) { 33 | Arrays.sort(S); 34 | int len = S.length; 35 | ArrayList> subsets = new ArrayList>(); 36 | //subsets.add(new ArrayList()); //for adding the empty list 37 | for(int i = 0; i < Math.pow(2,len); i++) { //O( 2^len * len) not sure 38 | int count = 0, t = i; 39 | ArrayList subset = new ArrayList(); 40 | for( ;t != 0; count++, t=t>>1) { //O(len) 41 | // while(t != 0) { 42 | if((t & 1) != 0) { 43 | subset.add(S[count]); 44 | } 45 | // count++; 46 | // t = t >> 1; 47 | } 48 | 49 | subsets.add(subset); 50 | } 51 | return subsets; 52 | } 53 | 54 | public static void main (String[] args) throws java.lang.Exception 55 | { 56 | Subsets program = new Subsets(); 57 | int[] S = {1,2,3}; 58 | ArrayList> result = program.subsets(S); 59 | for(ArrayList subset: result) { 60 | System.out.print("[ "); 61 | for(Integer element:subset) { 62 | System.out.print(element + ", "); 63 | } 64 | System.out.println("]"); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Swap/README.md: -------------------------------------------------------------------------------- 1 | ## How does it work ? 2 | For example, let, 3 | ```c 4 | x = 10111101; 5 | y = 00101110; 6 | ``` 7 | Step 1, 8 | ```c 9 | x = x ^ y; 10 | 11 | x == 10010011; <= changed 12 | y == 00101110; 13 | ``` 14 | Step 2, 15 | ```c 16 | y = x ^ y; 17 | 18 | x == 10010011; 19 | y == 10111101; <= changed 20 | ``` 21 | Step 3, 22 | ```c 23 | x = x ^ y; 24 | 25 | x == 00101110; <= changed 26 | y == 10111101; 27 | ``` 28 | ## Why does it work ? 29 | XOR is its own inverse: 30 | ```c 31 | (x ^ y) ^ y = x; 32 | (x ^ y) ^ x = y; 33 | ``` 34 | ## Performance 35 | Poor at exploiting instruction-level parallelism (ILP). 36 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Swap/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const int A = 10; 5 | const int B = 11; 6 | 7 | void swap(int &x, int &y) 8 | { 9 | x = x ^ y; 10 | y = x ^ y; 11 | x = x ^ y; 12 | } 13 | 14 | int main() 15 | { 16 | int a = A; 17 | int b = B; 18 | swap(a, b); 19 | assert(a == B); 20 | assert(b == A); 21 | std::cout << "All asserts passed" << std::endl; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/Swap/main.swift: -------------------------------------------------------------------------------- 1 | /* Swap with out using temp inPlace 2 | @param x:Int 3 | @param y:Int 4 | @return none 5 | */ 6 | 7 | func swap(inout x:Int, inout y:Int) { 8 | x = x ^ y 9 | y = y ^ x 10 | x = x ^ y 11 | } 12 | 13 | //testing in playground 14 | var a = 10 15 | var b = 11 16 | swap(&a, &b) 17 | a 18 | b 19 | -------------------------------------------------------------------------------- /05_Bit_Manipulation/bit_hacks.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alxerg/Interview-Questions/ac05100917cdc9b486218eeb091baaac38a84639/05_Bit_Manipulation/bit_hacks.pdf -------------------------------------------------------------------------------- /06_Math_and_Logic_Puzzles/README.md: -------------------------------------------------------------------------------- 1 | # Math and Logic Puzzles 2 | -------------------------------------------------------------------------------- /07_Object-Oriented_Design/README.md: -------------------------------------------------------------------------------- 1 | # Object oriented design 2 | 3 | * Write a high level design for a File System [SO answer](http://stackoverflow.com/questions/5509353/interview-q-design-file-system-review), [Composite design pattern](https://sourcemaking.com/design_patterns/composite/java/1) 4 | 5 | * Design a vending machine like coffee vending machine [Blog help](http://k2code.blogspot.in/2014/04/design-vending-machine-like-coffee.html) 6 | 7 | ## Sources 8 | 9 | * [Nice resource](http://k2code.blogspot.in/search/label/object-oriented-design%20%2F%20OOD) 10 | * [Top questions about design patterns on SO](http://stackoverflow.com/questions/tagged/design-patterns?sort=votes&pageSize=15) 11 | * [A nice pdf with Q&A - should be transferred here - TODO](http://www.andiamogo.com/S-OOD.pdf) 12 | 13 | ### Learn this to think spontaneously on an interview 14 | 15 | ![Design patterns](http://i.imgur.com/2h4FWtl.png) 16 | -------------------------------------------------------------------------------- /07_Object-Oriented_Design/Url_shortner/README.md: -------------------------------------------------------------------------------- 1 | ## Design a URL shortner service 2 | 3 | #### Usage: 4 | url_shortner.py "www.santhosh.info" 5 | url_shortner.py "www.prakashn.com" 6 | 7 | 8 | ####TODO: 9 | Create a table for adding all the urls and creating a table id 10 | -------------------------------------------------------------------------------- /07_Object-Oriented_Design/Url_shortner/url_shortner.py: -------------------------------------------------------------------------------- 1 | # design a tiny URL or URL shortener 2 | import sys; 3 | 4 | # Algorithm 5 | # 1. place the long url in db table 6 | # 2. get the rowid from the table and convert it into short url (id_to_short_url) 7 | # 3. convert back the short url into rowid and get the long url (short_url_to_id) 8 | 9 | # change the rowid to short url 10 | def id_to_short_url(db_id): 11 | # a to z = 26 12 | # A to Z = 26 13 | # 0 to 9 = 10 14 | # total there are 62 possible letters 15 | map = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQUSTUVWXYZ0123456789' 16 | short_url = '' 17 | while(db_id != 0): 18 | index = db_id % 62 19 | short_url += map[index] 20 | db_id = db_id / 62 21 | return short_url 22 | 23 | # change the short url to row id 24 | def short_url_to_id(short_url): 25 | db_id = 0; 26 | for letter in short_url: 27 | if(letter >= 'a' and letter <= 'z'): 28 | db_id = db_id * 62 + ord(letter) - ord('a') 29 | if(letter >= 'A' and letter <= 'Z'): 30 | db_id = db_id * 62 + ord(letter) - ord('A') + 26 #adding values to match it with the map string 31 | if(letter >= '0' and letter <= '9'): 32 | db_id = db_id * 62 + ord(letter) - ord('0') + 52 33 | return db_id 34 | 35 | def main(arg): 36 | long_url = arg 37 | # place the long url in the DB and 38 | # get the row id from the table 39 | # let us assume that the row id is 12345 40 | row_id = 12345 41 | print "row id is {0}".format(row_id) 42 | short_url = id_to_short_url(row_id) 43 | short_url = short_url[::-1] # reverse it to calculate the id from the starting 44 | print "short_url is {0}".format(short_url); 45 | print "db_id is {0}".format(short_url_to_id(short_url)) 46 | 47 | if __name__ == "__main__": 48 | main(sys.argv[1:]) 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/CuttingRod/README.md: -------------------------------------------------------------------------------- 1 | [Dynamic Programming - Rod Cutting](http://www.radford.edu/~nokie/classes/360/dp-rod-cutting.html) 2 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/CuttingRod/cuttingRod.java: -------------------------------------------------------------------------------- 1 | package CuttingRod; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class cuttingRod { 7 | public static int naive(int price[], int n) { 8 | if (n <= 0) 9 | return 0; 10 | int max_val = Integer.MIN_VALUE; 11 | // Recursively cut the rod in different pieces and compare different configurations 12 | for (int i = 1; i<=n; i++) 13 | max_val = Math.max(max_val, price[i] + naive(price, n-i)); 14 | return max_val; 15 | } 16 | static Map cache = new HashMap(); 17 | public static int memoizedTopDown(int price[], int n) { 18 | if (cache.containsKey(n)) { 19 | return cache.get(n); 20 | } 21 | if (n <= 0) { 22 | cache.clear(); // static cache, so clear on first call 23 | return 0; 24 | } 25 | int max_val = Integer.MIN_VALUE; 26 | for (int i = 1; i<=n; i++) 27 | max_val = Math.max(max_val, price[i] + memoizedTopDown(price, n-i)); 28 | cache.put(n, max_val); 29 | return max_val; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/CuttingRod/cuttingRodTest.java: -------------------------------------------------------------------------------- 1 | package CuttingRod; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | public class cuttingRodTest { 8 | int clrsArr[] = {0, 1, 5, 8, 9, 10, 17, 17, 20}; //pg 361 - p[i] = price of rod of length i 9 | @Test 10 | public void testNaive() { 11 | assertEquals(10, cuttingRod.naive(clrsArr, 4)); 12 | } 13 | @Test 14 | public void testMemoizedTopDown() { 15 | assertEquals(10, cuttingRod.memoizedTopDown(clrsArr, 4)); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/EditDistance/README.md: -------------------------------------------------------------------------------- 1 | # Edit Distance 2 | ## Question 3 | ``` 4 | Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) 5 | 6 | You have the following 3 operations permitted on a word: 7 | 8 | a) Insert a character 9 | b) Delete a character 10 | c) Replace a character 11 | ``` 12 | 13 | 14 | ## Techniques: 15 | * Recursion 16 | * Dynamic programming for optimization 17 | 18 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/EditDistance/Solution.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def minDistance(self, w1, w2): 3 | """ 4 | :type word1: str 5 | :type word2: str 6 | :rtype: int 7 | """ 8 | # TLE 9 | # def mind(w1, w2, m, n): 10 | # if not m: 11 | # return n # insert n characters to match 12 | # if not n: 13 | # return m # delete m characters 14 | # if w1[m-1] == w2[n-1]: 15 | # return mind(w1, w2, m-1, n-1) 16 | # else: 17 | # return 1+min(mind(w1,w2, m, n-1), min(mind(w1,w2, m-1, n), mind(w1,w2,m-1,n-1))) 18 | # return mind(w1, w2, len(w1), len(w2)) 19 | 20 | # DP solution 21 | m = len(w1) 22 | n = len(w2) 23 | dp = [[0] * (n+1) for _ in range(m+1)] 24 | for i in range(m+1): 25 | for j in range(n+1): 26 | if i == 0: 27 | dp[i][j] = j # insert j characters 28 | continue 29 | if j == 0: 30 | dp[i][j] = i # delete i characters 31 | continue 32 | if w1[i-1] == w2[j-1]: 33 | dp[i][j] = dp[i-1][j-1] 34 | else: 35 | dp[i][j] = 1+min(dp[i-1][j], min(dp[i][j-1], dp[i-1][j-1])) 36 | print(dp) 37 | return dp[m][n] 38 | 39 | pgm = Solution() 40 | w1 = "INTENTION" 41 | w2 = "EXECUTION" 42 | print( pgm.minDistance(w1, w2)) 43 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/Fibonacci_Number/README.md: -------------------------------------------------------------------------------- 1 | ## Fibonacci 2 | ``` 3 | The Fibonacci numbers are the numbers in the following integer sequence. 4 | 5 | 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 141, …….. 6 | 7 | In mathematical terms, the sequence Fn of Fibonacci numbers is defined by the recurrence relation 8 | 9 | Fn = Fn-1 + Fn-2 10 | with seed values 11 | 12 | F0 = 0 and F1 = 1. 13 | ``` -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/Fibonacci_Number/fib.py: -------------------------------------------------------------------------------- 1 | def getFib(n): 2 | if n < 2: 3 | return n 4 | first = 0 5 | second = 1 6 | third = 0 7 | for i in range( 2, n + 1): 8 | third = first + second 9 | first = second 10 | second = third 11 | return second 12 | 13 | if __name__ == '__main__': 14 | print "the number is {0}".format(getFib(6)) -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/Hanoi/ReadMe.md: -------------------------------------------------------------------------------- 1 | ## Towers of Hanoi Problem 2 | ``` 3 | Towers of Hanoi is a puzzle that consists of three posts, and a set of disks of different sizes 4 | with holes in the middle so that the disks can be stacked on the posts. You start with all disks 5 | stacked on one post, ranging from smallest to largest, top to bottom. Your job is to transfer the 6 | stack from the first post to the third, using the second post for temporary storage. 7 | You can only move one disk at a time, and you can never place a larger disk on 8 | top of a smaller disk. 9 | ``` 10 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/Hanoi/Solution.java: -------------------------------------------------------------------------------- 1 | /* package whatever; // don't place package name! */ 2 | 3 | import java.util.*; 4 | import java.lang.*; 5 | import java.io.*; 6 | 7 | /* Name of the class has to be "Main" only if the class is public. */ 8 | class Solution 9 | { 10 | static void hanoi(int height, int first, int temp, int final1) 11 | { 12 | if (height <= 0) return; 13 | hanoi (height-1, first, final1, temp); 14 | System.out.println("Move disk "+ height +" from " + first +" to "+final1); 15 | hanoi (height-1, temp, first, final1); 16 | } 17 | public static void main (String[] args) throws java.lang.Exception 18 | { 19 | hanoi(3,1,2,3); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/MobileNumericKeypadProblem/README.md: -------------------------------------------------------------------------------- 1 | # Mobile Numeric Keypad Problem 2 | 3 | ## [Problem](https://www.geeksforgeeks.org/mobile-numeric-keypad-problem/): 4 | ``` 5 | Given the mobile numeric keypad. You can only press buttons that are up, left, right or down to the current button. 6 | You are not allowed to press bottom row corner buttons (i.e. * and # ). 7 | 8 | Given a number N, find out the number of possible numbers of given length. 9 | ``` 10 | 11 | ## Approach: 12 | ``` 13 | 1) construct the adjcency list of nearby keys 14 | 2) let dp[N][k] be the count of keys that can be pressed starting from k with count N. 15 | 3) base case: dp[1][j] = 1 for all j in range(10) 16 | 4) recursive relation: dp[i][j] = dp[i-1][j] + sum([dp[i-1][k] for k in adjacency[j]) 17 | ``` 18 | 19 | 20 | ## Runtime 21 | Time : `O(N * K * 4)` here N is number of buttons pressed, K is total keys, 4 is max value in adjacency list 22 | Space: `O((N+1)*10)` 23 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/MobileNumericKeypadProblem/solution.py: -------------------------------------------------------------------------------- 1 | """ 2 | Given the mobile numeric keypad. You can only press buttons that are up, left, right or down to the current button. 3 | You are not allowed to press bottom row corner buttons (i.e. * and # ) 4 | Given a number N, find out the number of possible numbers of given length. 5 | 6 | https://www.geeksforgeeks.org/mobile-numeric-keypad-problem/ 7 | 8 | """ 9 | 10 | 11 | def count(N): 12 | # format the keypad as adj list 13 | adj = [ 14 | [8], 15 | [2,4], 16 | [1,5,3], 17 | [2,6], 18 | [1,5,7], 19 | [2,4,6,8], 20 | [3,5,9], 21 | [4,8], 22 | [5,7,9,0], 23 | [6,8] 24 | ] 25 | K = 10 26 | dp = [ [0]*K for _ in range(N+1)] 27 | 28 | # base case 29 | for j in range(K): 30 | dp[1][j] = 1 31 | # print("value of ", 1, " = ", sum(dp[1])) 32 | 33 | # iterative approach 34 | for i in range(2,N+1): 35 | for j in range(K): 36 | dp[i][j] = dp[i-1][j] 37 | for v in adj[j]: 38 | dp[i][j] += dp[i-1][v] 39 | # print("value of ", i, " = ", sum(dp[i])) 40 | return sum(dp[-1]) 41 | 42 | if __name__ == "__main__": 43 | print(count(10)) 44 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/Permutations/README.md: -------------------------------------------------------------------------------- 1 | # Generate all permutations 2 | ``` 3 | TimeComplexity = O(n!) 4 | ``` 5 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/Permutations/permutations.py: -------------------------------------------------------------------------------- 1 | # generate all permutations 2 | a = ['A', 'B', 'C', 'D', 'E'] 3 | 4 | 5 | def permutation(arr, cur, v, res): 6 | # print(cur, v) 7 | if len(cur) == len(a): 8 | res.append(cur) 9 | return 10 | 11 | for i in range(len(a)): 12 | if not v[i]: 13 | v[i] = True 14 | permutation(arr, cur + arr[i], v, res) 15 | v[i] = False 16 | 17 | res = [] 18 | visited = [False] * len(a) 19 | permutation(a, "", visited, res) 20 | print(res) 21 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/README.md: -------------------------------------------------------------------------------- 1 | # Recursion and dynamic programming 2 | 3 | 1. ✔ Given any amount of cents the code will return an array with the minimum amount of coins that add up to the required amount. The array should be arranged from highest to lowest value coin. - **coinChanger** 4 | 2. ✔ Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) - **editDistance** 5 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/SubsetsGeneration/README.md: -------------------------------------------------------------------------------- 1 | # Generate all Subsets 2 | ``` 3 | Time Complexity: O(2 ^ n) 4 | ``` 5 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/SubsetsGeneration/solution.py: -------------------------------------------------------------------------------- 1 | a = ['a','b','c','d'] 2 | def subset(arr, cur, res, ind): 3 | # print(cur, ind) 4 | if ind > len(arr): 5 | return 6 | if ind == len(arr): 7 | test = list(cur) 8 | res.append(test) 9 | return 10 | subset(arr, cur, res, ind+1) 11 | cur.append(arr[ind]) 12 | subset(arr, cur, res, ind+1) 13 | cur.pop() 14 | 15 | res = [] 16 | subset(a, [], res, 0) 17 | print(res) 18 | print(len(res)) 19 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/Ugly_Numbers/README.md: -------------------------------------------------------------------------------- 1 | ##Ugly Numbers 2 | ``` 3 | Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence 4 | 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, … 5 | shows the first 11 ugly numbers. By convention, 1 is included. 6 | Write a program to find and print the 150’th ugly number. 7 | ``` -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/Ugly_Numbers/uglynumbers.py: -------------------------------------------------------------------------------- 1 | __author__ = "Prakash Natarajan" 2 | 3 | """ 4 | Here is a time efficient solution with O(n) extra space. The ugly-number sequence is 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, … 5 | because every number can only be divided by 2, 3, 5, one way to look at the sequence is to split the sequence to three groups as below: 6 | (1) 1×2, 2×2, 3×2, 4×2, 5×2, … 7 | (2) 1×3, 2×3, 3×3, 4×3, 5×3, … 8 | (3) 1×5, 2×5, 3×5, 4×5, 5×5, … 9 | 10 | We can find that every subsequence is the ugly-sequence itself (1, 2, 3, 4, 5, …) multiply 2, 3, 5. Then we use similar merge method as merge sort, to get every ugly number from the three subsequence. Every step we choose the smallest one, and move one step after. 11 | source: http://www.geeksforgeeks.org/ugly-numbers/ 12 | """ 13 | def getUglyNumber(n): 14 | # @input n int 15 | # @output int nth ugly number 16 | ugly = [0] * (n) 17 | count = 1 18 | ugly[0] = 1 19 | i2 = i3 = i5 = 0 20 | multiple_of_2 = 2 21 | multiple_of_3 = 3 22 | multiple_of_5 = 5 23 | while(count < n): 24 | # output n-1 25 | next_number = min(multiple_of_2, 26 | multiple_of_3, 27 | multiple_of_5) 28 | if next_number == multiple_of_2: 29 | i2 += 1 30 | ugly[count] = next_number 31 | multiple_of_2 = ugly[i2] * 2 32 | # count +=1 33 | elif next_number == multiple_of_3 : 34 | i3 += 1 35 | multiple_of_3 = ugly[i3] * 3 36 | if next_number in ugly: 37 | continue 38 | ugly[count] = next_number 39 | elif next_number == multiple_of_5 : 40 | i5 += 1 41 | multiple_of_5 = ugly[i5] * 5 42 | if next_number in ugly: 43 | continue 44 | ugly[count] = next_number 45 | count += 1 46 | print ugly 47 | print len(ugly) 48 | return ugly[n-1] 49 | 50 | if __name__ == '__main__': 51 | print getUglyNumber(150) 52 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/WaysToWriteN/DynamicSolution.java: -------------------------------------------------------------------------------- 1 | /* package whatever; // don't place package name! */ 2 | 3 | import java.util.*; 4 | import java.lang.*; 5 | import java.io.*; 6 | 7 | class DynamicSolution 8 | { 9 | static int[] res; 10 | static int[] arr; 11 | public static void main (String[] args) throws java.lang.Exception 12 | { 13 | int n = 40; 14 | res = new int[n+1]; 15 | arr = new int[] {1, 3, 4}; 16 | for(int i = 0; i <= n; i++) { 17 | sol(n); 18 | } 19 | System.out.println(res[n]); 20 | } 21 | static int sol(int n) { 22 | if(n < 0) return 0; 23 | if(n == 0) return 1; 24 | if(res[n] != 0) return res[n]; 25 | int r = 0; 26 | for (int a : arr) { 27 | r += sol(n-a); 28 | } 29 | res[n] = r; 30 | return r; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/WaysToWriteN/Readme.md: -------------------------------------------------------------------------------- 1 | # Problem: 2 | ``` 3 | given n, find the number of different ways to write 4 | n as the sum of 1, 3, 4 5 | ``` 6 | ## Example: 7 | ``` 8 | for n = 5, the answer is 6 9 | 5 = 1 + 1 + 1 + 1 + 1 10 | = 1 + 1 + 3 11 | = 1 + 3 + 1 12 | = 3 + 1 + 1 13 | = 1 + 4 14 | = 4 + 1 15 | ``` 16 | 17 | ## Result: 18 | for n = 40, Dynamic solution took `0.06s` while recursive solution took `1.35s` 19 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/WaysToWriteN/RecusiveSolution.java: -------------------------------------------------------------------------------- 1 | 2 | import java.util.*; 3 | import java.lang.*; 4 | import java.io.*; 5 | 6 | 7 | class RecusiveSolution 8 | { 9 | static int cnt; 10 | static int[] arr; 11 | public static void main (String[] args) throws java.lang.Exception 12 | { 13 | int n = 40; 14 | cnt = 0; 15 | arr = new int[] {1, 3, 4}; 16 | sol(n); 17 | System.out.println(cnt); 18 | } 19 | 20 | static void sol(int n) { 21 | if(n < 0) return; 22 | if(n == 0) { 23 | cnt++; 24 | return; 25 | } 26 | for(int a : arr) { 27 | sol(n-a); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/coinChanger/README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | 3 | # The point of this exercise is to create a change maker. That is, given any amount of cents the code will return an array with the minimum amount of coins that add up to the required amount. The array should be arranged from highest to lowest value coin. 4 | # 5 | # A working version will provide the output specified below: 6 | # 7 | # ChangeMaker.makeChange(0) => [] 8 | # ChangeMaker.makeChange(26) => [25, 1] 9 | # ChangeMaker.makeChange(24) => [10, 10, 1, 1, 1, 1] 10 | # ChangeMaker.makeChange(49) => [25, 10, 10, 1, 1, 1, 1] 11 | # ChangeMaker.makeChange(26, new int[] {10, 25, 1, 5}) => [25, 1] 12 | # ChangeMaker.makeChange(14, new int[] {10, 7, 1}) => [7, 7] 13 | # 14 | ``` -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/coinChanger/Solution.java: -------------------------------------------------------------------------------- 1 | import java.util.*; 2 | 3 | public class Solution { 4 | static int coinChange(int[] s, int n, int i) { 5 | if (n == 0) return 1; 6 | if(i == s.length || n < 0) return 0; 7 | return coinChange(s, n, i+1) + // not included 8 | coinChange(s, n-s[i], i); 9 | } 10 | public static void main(String[] args){ 11 | int[] s = {2, 5, 3, 6}; 12 | int n = 10; 13 | System.out.println(coinChange(s, n, 0)); 14 | } 15 | } -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/coinChanger/solution.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | # @input inp_ele int 3 | # arr array 4 | def changeMakerHelper(self, inp_ele, arr, res_arr, index): 5 | #base case 6 | if index > len(arr): 7 | return 8 | if inp_ele == 0: 9 | return 10 | 11 | 12 | if inp_ele >= arr[index]: # 26 >= 25 13 | res_arr.append(arr[index]) 14 | self.changeMakerHelper(inp_ele - arr[index], arr, res_arr, index) 15 | else: 16 | # increment the index and check recursively 17 | self.changeMakerHelper(inp_ele, arr, res_arr, index + 1) 18 | 19 | def changeMaker(self, inp_ele, arr): 20 | arr = sorted(arr,reverse = True) 21 | res_arr = [] 22 | self.changeMakerHelper(inp_ele, arr, res_arr, 0) 23 | print res_arr 24 | 25 | def changeMakerNewHelper(self, inp_ele, arr, res_arr, index): 26 | temp_list = [x for x in arr if x >= (inp_ele/2)] 27 | for item in temp_list: 28 | if inp_ele % item == 0: 29 | # res = [item] * (inp_ele / item) 30 | for i in range(inp_ele / item): 31 | res_arr.append(item) 32 | return; 33 | if index > len(arr): 34 | return 35 | if inp_ele == 0: 36 | return 37 | 38 | 39 | if inp_ele >= arr[index]: # 26 >= 25 40 | res_arr.append(arr[index]) 41 | self.changeMakerHelper(inp_ele - arr[index], arr, res_arr, index) 42 | else: 43 | # increment the index and check recursively 44 | self.changeMakerHelper(inp_ele, arr, res_arr, index + 1) 45 | 46 | 47 | 48 | 49 | 50 | def changeMakerNew(self, inp_ele, arr = [10, 25, 1, 5]): 51 | arr = sorted(arr,reverse = True) 52 | res = [] 53 | self.changeMakerNewHelper(inp_ele, arr, res, 0) 54 | print res 55 | 56 | 57 | pgm = Solution() 58 | pgm.changeMakerNew(26) 59 | pgm.changeMakerNew(24) 60 | pgm.changeMakerNew(49) 61 | # ChangeMaker.makeChange(26, new int[] {10, 25, 1, 5}) => [25, 1] 62 | # ChangeMaker.makeChange(14, new int[] {10, 7, 1}) 63 | pgm.changeMakerNew(26, [10, 25, 1, 5]) 64 | pgm.changeMakerNew(14, [10, 7, 1]) -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/kthPermutation/README.md: -------------------------------------------------------------------------------- 1 | ## Return the kth permutation 2 | 3 | ``` 4 | The set [1,2,3,…,n] contains a total of n! unique permutations. 5 | 6 | By listing and labeling all of the permutations in order, 7 | We get the following sequence (ie, for n = 3): 8 | 9 | "123" 10 | "132" 11 | "213" 12 | "231" 13 | "312" 14 | "321" 15 | Given n and k, return the kth permutation sequence. 16 | ``` -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/kthPermutation/kthPermutation.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | class Solution(object): 4 | 5 | # Time complexity O(2 ^ n) 6 | def getPermutation(self, n, k): 7 | char_list = map(str, range(1, n + 1)) #convert to strin 8 | used = [False] * len(char_list) 9 | result = [] 10 | kthArray = self._getPermutation_helper(result, char_list, used, [], k) 11 | print "kth array is" 12 | print kthArray #kthArray is always None 13 | return kthArray 14 | 15 | def _getPermutation_helper(self, result, char_list, used, cur, k): 16 | if len(char_list) == len(cur): 17 | result.append(cur + []) 18 | print len(result) 19 | print cur 20 | if len(result) == k: 21 | print "cur in kth is {0}".format(cur) 22 | return cur #cur is printed correctly but not returned 23 | for i in range(len(char_list)): 24 | if not used[i]: 25 | cur.append(char_list[i]) 26 | used[i] = True 27 | r = self._getPermutation_helper(result, char_list, used, cur, k) 28 | if r is not None: 29 | return r 30 | # back track 31 | used[i] = False 32 | cur.remove(char_list[i]) 33 | 34 | # O(n) solution if factorial talkes constant time 35 | """ 36 | Idea: 37 | 1) get the index of the element which is selected each time in the recursion 38 | 2) remove that element and add it to result. 39 | 3) repeat this until n becomes 0 40 | """ 41 | def getPerm(self, n, k): 42 | num_arr = map(str,range(1, n + 1)) 43 | k -= 1 44 | result = '' 45 | while n: 46 | n -= 1 47 | index , k = divmod(k, math.factorial(n)) 48 | result += num_arr.pop(index) 49 | return result 50 | 51 | def main(): 52 | pgm = Solution() 53 | print pgm.getPermutation(3, 6) 54 | print pgm.getPerm(3, 6) 55 | if __name__ == "__main__": 56 | main() -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/longestGeometricProgression/README.md: -------------------------------------------------------------------------------- 1 | # Longest Geometric Progression 2 | 3 | ### Problem 4 | Given a set of numbers, find the Length of the Longest Geometrix Progression (LLGP) in it. The common ratio of GP must be an integer. 5 | 6 | ### Examples: 7 | ``` 8 | set[] = {5, 7, 10, 15, 20, 29} 9 | output = 3 10 | The longest arithmetic progression is {5, 10, 20} 11 | 12 | set[] = {3, 9, 27, 81} 13 | output = 4 14 | ``` 15 | -------------------------------------------------------------------------------- /08_Recursion_and_Dynamic_Programming/longestGeometricProgression/solution.py: -------------------------------------------------------------------------------- 1 | A = [3, 9, 27, 81] 2 | n = len(A) 3 | dp = [1]*n 4 | for i in range(1, n): 5 | for j in range(i): 6 | if A[i] % A[j] == 0: 7 | dp[i] = max(dp[i], dp[j]+1) 8 | print("count:",max(dp)) 9 | -------------------------------------------------------------------------------- /09_System_Design_and_Scalability/Heap/MinHeap.py: -------------------------------------------------------------------------------- 1 | class Heap(object): 2 | def __init__(self): 3 | self.arr = [None] # ind 0 is None 4 | 5 | def is_empty(self): 6 | return len(self.arr) <= 1 7 | 8 | def heappush(self, val): 9 | self.arr.append(val) 10 | self.__swim(len(self.arr)-1) 11 | # print("after push", self.arr[1:]) 12 | 13 | def heappop(self): 14 | ret = self.arr[1] 15 | self.arr[1] = self.arr[-1] 16 | self.arr = self.arr[:-1] 17 | self.__sink(1) 18 | # print("after pop", self.arr[1:]) 19 | return ret 20 | 21 | def __swim(self, idx): 22 | parent = idx//2 23 | while parent >= 1 and self.arr[idx] < self.arr[parent]: 24 | self.arr[parent], self.arr[idx] = self.arr[idx], self.arr[parent] 25 | idx = parent 26 | parent = idx//2 27 | def __sink(self, idx): 28 | lc, rc = idx*2, idx*2+1 29 | while idx < len(self.arr) and lc < len(self.arr): 30 | if rc >= len(self.arr): rc = lc 31 | min_idx = lc if self.arr[lc] < self.arr[rc] else rc 32 | min_child = self.arr[min_idx] 33 | if self.arr[idx] <= min_child: break 34 | self.arr[idx], self.arr[min_idx] = self.arr[min_idx], self.arr[idx] 35 | if lc == rc: break 36 | idx = lc if self.arr[lc] < self.arr[rc] else rc 37 | lc, rc = idx * 2, idx * 2 + 1 38 | 39 | minheap = Heap() 40 | for a in [5,2,3,1,4,4]: 41 | minheap.heappush(a) 42 | while not minheap.is_empty(): 43 | print(minheap.heappop()) 44 | -------------------------------------------------------------------------------- /09_System_Design_and_Scalability/Heap/README.md: -------------------------------------------------------------------------------- 1 | # Design Heap 2 | ``` 3 | Design Minheap implementation from scratch 4 | ``` 5 | -------------------------------------------------------------------------------- /09_System_Design_and_Scalability/README.md: -------------------------------------------------------------------------------- 1 | # System design and scalability 2 | 3 | - [Another System design interview repo](https://github.com/checkcheckzz/system-design-interview) 4 | - [Design Patterns explained with real world example](https://github.com/kamranahmedse/design-patterns-for-humans) 5 | -------------------------------------------------------------------------------- /10_Sorting_and_Searching/README.md: -------------------------------------------------------------------------------- 1 | # Sorting and searching 2 | 3 | | Algorithm | Data Structure | Time Complexity | | | Space Complexity 4 | | :------------: | :---------------: | :-----: | :-----: | :-----: | :-----: | 5 | | | | Best | Average | Worst | Worst 6 | | Quicksort | Array | O(n log(n)) | O(n log(n)) | O(n^2) | O(n log(n)) 7 | | Mergesort |Array | O(n log(n)) | O(n log(n)) | O(n log(n)) | O(n) 8 | | Heapsort | Array | O(n log(n)) | O(n log(n)) | O(n log(n)) | O(1) 9 | | Bubble Sort | Array | O(n) | O(n^2) | O(n^2) | O(1) 10 | | Insertion Sort | Array | O(n) | O(n^2) | O(n^2) | O(1) 11 | | Select Sort | Array | O(n^2) | O(n^2) | O(n^2) | O(1) 12 | | Bucket Sort | Array | O(n+k) | O(n+k) | O(n^2) | O(n) 13 | | Radix Sort | Array | O(nk) | O(nk) | O(nk) | O(n + k) 14 | -------------------------------------------------------------------------------- /11_Testing/README.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | -------------------------------------------------------------------------------- /12_Language_Based_Questions/Android_Questions.md: -------------------------------------------------------------------------------- 1 | * how do you deal with ContentProviders? 2 | * [How do you get Activities and Fragments to communicate with each-other?](https://github.com/codepath/android_guides/wiki/Creating-and-Using-Fragments#communicating-with-fragments) 3 | * [What is the MVC pattern?](https://medium.com/android-news/android-architecture-2f12e1c7d4db) 4 | * Do you know any other design patterns outside of MVC? 5 | * [What does the android post method do?](http://stackoverflow.com/questions/13840007/what-exactly-does-the-post-method-do) 6 | * [how to handle configuration changes in Activitys (i.e. when you rotate the screen, etc.)](https://github.com/codepath/android_guides/wiki/Handling-Configuration-Changes#saving-and-restoring-activity-state) - [#2](http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html) - [ #3](http://stackoverflow.com/questions/3821423/background-task-progress-dialog-orientation-change-is-there-any-100-working) 7 | 8 | ## References 9 | * [Had a difficult interview, maybe some of you will find the questions useful](https://www.reddit.com/r/androiddev/comments/3hgeez/had_a_difficult_interview_maybe_some_of_you_will/) 10 | * [I'm going into my first technical Android interview on Tuesday, what will my interviewers look for?](https://www.reddit.com/r/androiddev/comments/2olt9f/im_going_into_my_first_technical_android/) 11 | * [What type of interview questions should I expect for an Android dev position?](https://www.reddit.com/r/androiddev/comments/1oe5bq/what_type_of_interview_questions_should_i_expect/) 12 | * [I have my first interview for an Android Software Internship position soon. Any tips, hints, possible questions?](https://www.reddit.com/r/androiddev/comments/112yj5/i_have_my_first_interview_for_an_android_software/) 13 | -------------------------------------------------------------------------------- /12_Language_Based_Questions/Java_questions.md: -------------------------------------------------------------------------------- 1 | * If we use final on a Java object, can the variables and data structures inside that Java object be modified? [Quora-1](http://www.quora.com/If-we-use-final-on-a-Java-object-can-the-variables-and-data-structures-inside-that-Java-object-be-modified) 2 | * What happens when you declare a class final? [SO-1](http://stackoverflow.com/a/12335925/3394023) 3 | * Explain static classes in Java? [SO-1](http://stackoverflow.com/questions/3584113/why-are-you-not-able-to-declare-a-class-as-static-in-java) [SO-2](http://stackoverflow.com/questions/7486012/static-classes-in-java?lq=1) 4 | * Compiled Vs Intrepreted [SO-1](http://stackoverflow.com/questions/3265357/compiled-vs-interpreted-languages) 5 | * Difference between keywords final/finally/finalize [SO-1](http://stackoverflow.com/questions/7814688/in-java-what-purpose-do-the-keywords-final-finally-and-finalize-fulfil) 6 | * Difference between checked and unchecked exceptions [SO-1](http://stackoverflow.com/questions/2699580/difference-between-unchecked-exception-or-runtime-exception) 7 | * When to use LinkedList over ArrayList? [SO-1](http://stackoverflow.com/questions/393556/when-to-use-a-linked-list-over-an-array-array-list) [SO-2](http://stackoverflow.com/questions/322715/when-to-use-linkedlist-over-arraylist) 8 | * Difference between HashMap, LinkedHashMap and TreeMap [SO-1](http://stackoverflow.com/questions/2889777/difference-between-hashmap-linkedhashmap-and-treemap) 9 | * Abstract Class vs Interface [SO-1](http://stackoverflow.com/questions/761194/interface-vs-abstract-class-general-oo) 10 | * Why do we hide data behind getters and setters? [SO-1](http://stackoverflow.com/questions/1568091/why-use-getters-and-setters) 11 | * Why calling public methods in a constructor is a bad practice? 12 | * Overriding vs overloading [SO-1](http://programmers.stackexchange.com/questions/164353/whats-the-difference-between-overloading-a-method-and-overriding-it-in-java) 13 | * try-catch-finally - in which order should the exceptions be handled? 14 | * What are generics? Why don't just use Object? [SO-1](http://stackoverflow.com/questions/5207115/java-generics-t-vs-object) 15 | * When should reflection be used and why you should avoid using it? 16 | * When are annotations used? 17 | -------------------------------------------------------------------------------- /12_Language_Based_Questions/Python.md: -------------------------------------------------------------------------------- 1 | # Python 2 | 3 | * What is the value of `ans` in the following code? - **[1,1]** - [Blog](http://effbot.org/zone/default-values.htm) 4 | ``` python 5 | >>> def function(data=[]): 6 | ... data.append(1) 7 | ... return data 8 | ... 9 | >>> function() 10 | [1] 11 | >>> ans = function() 12 | ``` 13 | -------------------------------------------------------------------------------- /12_Language_Based_Questions/README.md: -------------------------------------------------------------------------------- 1 | # Language specific Interview Questions 2 | -------------------------------------------------------------------------------- /12_Language_Based_Questions/cpp_questions.md: -------------------------------------------------------------------------------- 1 | * [What is virtual function and vtable in c++?](http://stackoverflow.com/questions/99297/how-are-virtual-functions-and-vtable-implemented) 2 | -------------------------------------------------------------------------------- /12_Language_Based_Questions/web_dev.md: -------------------------------------------------------------------------------- 1 | ## Web development Questions 2 | 3 | * [from Reddit](https://www.reddit.com/r/webdev/comments/3f7q3q/been_interviewing_with_a_lot_of_tech_startups_as) 4 | * [Front End Technical Interview Best Practices](http://popsnip.com/topic/36/Front-End-Interview-Techniques-and-Questions) 5 | -------------------------------------------------------------------------------- /13_Misc/LetterInOrder/README.md: -------------------------------------------------------------------------------- 1 | ## Letters in Alphabetical Order 2 | 3 | **Source:** https://www.reddit.com/r/dailyprogrammer/comments/3h9pde/20150817_challenge_228_easy_letters_in/ 4 | 5 | ``` 6 | A handful of words have their letters in alphabetical order, that is nowhere in the word do you change direction in the word if you were to scan along the English alphabet. An example is the word "almost", which has its letters in alphabetical order. 7 | Your challenge today is to write a program that can determine if the letters in a word are in alphabetical order. 8 | As a bonus, see if you can find words spelled in reverse alphebatical order. 9 | ``` -------------------------------------------------------------------------------- /13_Misc/LetterInOrder/Solution.py: -------------------------------------------------------------------------------- 1 | 2 | def letterInOrder(str): 3 | l = len(str) 4 | if l == 0 or l == 1: 5 | return True 6 | #container for holding the current max 7 | max = 0 8 | for i in range(l): 9 | if max > ord(str[i]): 10 | return False 11 | else: 12 | max = ord(str[i]) 13 | return True 14 | 15 | 16 | 17 | def main(): 18 | assert letterInOrder('almost') == True 19 | assert letterInOrder('cereal') == False 20 | print "all is well :)" 21 | 22 | if __name__ == "__main__": 23 | main() -------------------------------------------------------------------------------- /13_Misc/Must-Read-Links.md: -------------------------------------------------------------------------------- 1 | MUST READ LINKS BEFORE A WEEK for Interview: 2 | =========================================== 3 | 4 | 5 | 6 | * [Cracking the google interview](https://courses.csail.mit.edu/iap/interview/materials.php) 7 | * [Top 10 algorithms](http://www.programcreek.com/2012/11/top-10-algorithms-for-coding-interview/) 8 | * [How to break into a tech Interview?](http://haseebq.com/how-to-break-into-tech-job-hunting-and-interviews/) 9 | -------------------------------------------------------------------------------- /13_Misc/README.md: -------------------------------------------------------------------------------- 1 | # Misc - Yet to be categorized 2 | -------------------------------------------------------------------------------- /13_Misc/ReverseInteger/README.md: -------------------------------------------------------------------------------- 1 | ## Reverse Integer 2 | ``` 3 | Reverse digits of an integer. 4 | 5 | Example1: x = 123, return 321 6 | Example2: x = -123, return -321 7 | 8 | 9 | ``` -------------------------------------------------------------------------------- /13_Misc/ReverseInteger/Solution.java: -------------------------------------------------------------------------------- 1 | package info.santhosh.interview; 2 | 3 | import java.util.*; 4 | import java.lang.*; 5 | import java.io.*; 6 | 7 | class Main 8 | { 9 | public static int reverseInt(int x) { 10 | int rev = 0; 11 | while(x != 0){ 12 | rev = rev*10 + x%10; 13 | x = x/10; 14 | } 15 | return rev; 16 | } 17 | 18 | public static void main (String[] args) throws java.lang.Exception 19 | { 20 | System.out.println(reverseInt(321)); 21 | System.out.println(reverseInt(-321)); 22 | System.out.println(reverseInt(0)); 23 | /* 24 | 123 25 | -123 26 | 0 27 | */ 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /13_Misc/ReverseInteger/Solution.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def reverse(self, x): 3 | """ 4 | :type x: int 5 | :rtype: int 6 | """ 7 | negative = False 8 | #check for negation 9 | if x < 0: 10 | negative = True 11 | x = x * -1 12 | str_x = str(x) 13 | reversed_str = self.reverseString(str_x) 14 | if(negative): 15 | reversed_str = "-" + reversed_str 16 | result = int(reversed_str) 17 | if result > 2147483647 or result < -2147483647: 18 | return 0 19 | else: 20 | return result 21 | 22 | def reverseString(self, str): 23 | l = len(str) 24 | mid = l/2 25 | low = 0 26 | high = l-1 27 | list_x = list(str) 28 | for i in range(mid): 29 | temp = list_x[low] 30 | list_x[low] = list_x[high] 31 | list_x[high] = temp 32 | low += 1 33 | high -= 1 34 | return ''.join(list_x) 35 | 36 | def main(): 37 | print Solution().reverse(1534236469) 38 | if __name__ == "__main__": 39 | main() 40 | 41 | 42 | -------------------------------------------------------------------------------- /13_Misc/TopCoder/src/businessTasks/BusinessTasks.java: -------------------------------------------------------------------------------- 1 | package businessTasks; 2 | 3 | import java.util.ArrayList; 4 | 5 | 6 | /* Name of the class has to be "Main" only if the class is public. */ 7 | public class BusinessTasks { 8 | public static String getTask(String[] list, int n) { 9 | ArrayList al = new ArrayList(); 10 | for(int i=0; i 1) { 15 | cursor += (n-1); // from current cursor position move n-1 times 16 | cursor = cursor % al.size(); // get the index for the array 17 | System.out.format("%d mod %d = %d\n", n-1, al.size(), cursor); 18 | al.remove(cursor); 19 | } 20 | return al.get(0); 21 | } 22 | public static void main (String[] args) throws java.lang.Exception 23 | { 24 | System.out.println(getTask(new String[] {"a","b","c","d"}, 2)); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /13_Misc/TopCoder/src/businessTasks/BusinessTasksTest.java: -------------------------------------------------------------------------------- 1 | package businessTasks; 2 | 3 | import static org.junit.Assert.*; 4 | import hotel.Hotel; 5 | 6 | import org.junit.Test; 7 | 8 | public class BusinessTasksTest { 9 | private static String[] list = new String[]{"a","b","c","d"}; 10 | private static int n = 2; 11 | private static String result = "a"; 12 | @Test 13 | public void testGetTask1() { 14 | /* {"a","b","c","d"} 15 | 2 16 | Returns: "a"*/ 17 | list = new String[]{"a","b","c","d"}; 18 | n = 2; 19 | result = "a"; 20 | assertEquals(result, BusinessTasks.getTask(list, n)); 21 | } 22 | @Test 23 | public void testGetTask2() { 24 | /* {"a","b","c","d","e"} 25 | 3 26 | Returns: "d"*/ 27 | list = new String[]{"a","b","c","d","e"}; 28 | n = 3; 29 | result = "d"; 30 | assertEquals(result, BusinessTasks.getTask(list, n)); 31 | } 32 | @Test 33 | public void testGetTask3() { 34 | /* 35 | {"alpha","beta","gamma","delta","epsilon"} 36 | 1 37 | Returns: "epsilon" 38 | */ 39 | list = new String[]{"alpha","beta","gamma","delta","epsilon"}; 40 | n = 1; 41 | result = "epsilon"; 42 | assertEquals(result, BusinessTasks.getTask(list, n)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /13_Misc/TopCoder/src/cardStraights/CardStraights.java: -------------------------------------------------------------------------------- 1 | package cardStraights; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | import java.util.Set; 6 | import java.util.SortedSet; 7 | import java.util.TreeSet; 8 | 9 | /* https://community.topcoder.com/stat?c=problem_statement&pm=7417&rd=10661 10 | * Problem Statement 11 | 12 | You are playing a card game where the goal is to make straights. Each card in the deck has a number between 1 and 1000000, inclusive. 13 | A straight is a sequence of cards with consecutive values. Values do not wrap around, so 1 does not come after 1000000. 14 | In addition to regular cards, the deck also contains jokers. Each joker can be used as any valid number (between 1 and 1000000, inclusive). 15 | 16 | You will be given a int[] cards containing the cards in your hand. 17 | Jokers are represented by 0s, and other cards are represented by their values. 18 | Return the number of cards in the longest straight that can be formed using one or more cards from your hand. 19 | 20 | Constraints 21 | - cards will contain between 1 and 50 elements, inclusive. 22 | - Each element of cards will be between 0 and 1000000, inclusive. 23 | 24 | */ 25 | public class CardStraights { 26 | 27 | public static int longestStraight(final int[] cards) { 28 | // get only unique values, find the no of jokers and make them sorted 29 | SortedSet set = new TreeSet(); 30 | int jokersCount = 0; 31 | for (int c: cards) { 32 | if (c != 0) 33 | set.add(c); 34 | else 35 | jokersCount++; 36 | } 37 | Integer[] sortedCards = set.toArray(new Integer[set.size()]); 38 | // Find max 39 | int max = 0; 40 | for(int i=0; i < sortedCards.length; i++) { 41 | int diff = 0; 42 | int j; 43 | for(j=i+1; j < sortedCards.length; ) { // find the max straight with this card 44 | diff = diff + sortedCards[j] - sortedCards[j-1] - 1; // total difference observed 45 | if(diff <= jokersCount) // can this difference be filled by jokers? 46 | j++; // go to next card 47 | else break; 48 | } 49 | final int thisStraight = j-i; 50 | // update max if necessary 51 | if (max < thisStraight) 52 | max = thisStraight; 53 | } 54 | return max + jokersCount; 55 | } 56 | 57 | public static void main(String[] args) { 58 | CardStraights.longestStraight(new int[]{1,9,5,7,3,4,0,0,0,10}); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /13_Misc/TopCoder/src/cardStraights/CardStraightsTest.java: -------------------------------------------------------------------------------- 1 | package cardStraights; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | public class CardStraightsTest { 8 | 9 | @Test 10 | public void testLongestStraightBase() { 11 | /* 12 | Base case 13 | */ 14 | assertEquals(0, CardStraights.longestStraight(new int[]{})); 15 | } 16 | @Test 17 | public void testLongestStraight1() { 18 | /* 19 | {0,6,5,10,3,0,11} 20 | Returns: 5 21 | You can make 3-4-5-6-7 using one of your jokers as a 4 and the other one as a 7. 22 | */ 23 | assertEquals(5, CardStraights.longestStraight(new int[]{0,6,5,10,3,0,11})); 24 | } 25 | @Test 26 | public void testLongestStraight2() { 27 | /* 28 | {100,100,100,101,100,99,97,103} 29 | Returns: 3 30 | Not a very lucky hand. 31 | */ 32 | assertEquals(3, CardStraights.longestStraight(new int[]{100,100,100,101,100,99,97,103})); 33 | } 34 | @Test 35 | public void testLongestStraight3() { 36 | /* 37 | {0,0,0,1,2,6,8,1000} 38 | Returns: 6 39 | You can make 1-2-3-4-5-6 using your jokers cleverly. 40 | */ 41 | assertEquals(6, CardStraights.longestStraight(new int[]{0,0,0,1,2,6,8,1000})); 42 | } 43 | @Test 44 | public void testLongestStraight4() { 45 | /* 46 | {1,9,5,7,3,4,0,0,0,10} 47 | Returns: 10 48 | */ 49 | assertEquals(10, CardStraights.longestStraight(new int[]{1,9,5,7,3,4,0,0,0,10})); 50 | } 51 | @Test 52 | public void testLongestStraight5() { 53 | /* 54 | {0,0,1,2} 55 | Returns: 4 56 | Edge case where both jokers has to go the end 57 | */ 58 | assertEquals(4, CardStraights.longestStraight(new int[]{0,0,1,2})); 59 | } 60 | @Test 61 | public void testLongestStraight6() { 62 | /* 63 | {0,0} 64 | Returns: 2 65 | Edge case where only jokers are there 66 | */ 67 | assertEquals(2, CardStraights.longestStraight(new int[]{0,0})); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /13_Misc/TopCoder/src/hotel/Hotel.java: -------------------------------------------------------------------------------- 1 | package hotel; 2 | 3 | 4 | /* 5 | * https://community.topcoder.com/stat?c=problem_statement&pm=6254&rd=10766 6 | 7 | The hotel industry is difficult to thrive in, especially when competing at a resort city like Las Vegas. 8 | Marketing is essential and often gets a large part of total revenues. 9 | You have a list of cities you can market at, and a good estimate of how many customers you will get for a certain amount of money spent at each city. 10 | 11 | You are given int[]s customers and cost. cost[i] is the amount of money required to get customers[i] customers from the i-th city. 12 | You are only allowed to spend integer multiples of the cost for any city. 13 | For example, if it costs 9 to get 3 customers from a certain city, you can spend 9 to get 3 customer, 18 to get 6 customers, 27 to get 9 customers, but not 3 to get 1 customer, or 12 to get 4 customers. 14 | Each city has an unlimited number of potential customers. Return the minimum amount of money required to get at least minCustomers customers. 15 | 16 | Constraints 17 | - minCustomers will be between 1 and 1000, inclusive. 18 | - customers will contain between 1 and 20 elements, inclusive. 19 | - cost will have the same number of elements as customers. 20 | - Each element of cost and customers will be between 1 and 100, inclusive. 21 | */ 22 | public class Hotel { 23 | public static int marketCost(int minCustomers, int[] customers, int[] cost) { 24 | // Avoiding out of bounds 25 | int[] minSoln = new int[minCustomers+1]; // at index i store the minimum cost required to get atleast i customers 26 | int len = customers.length; 27 | for (int i = 1 ; i <= minCustomers ; i++) { // FIND ALL OPTIMAL COSTS <= MINCUSTOMERS 28 | minSoln[i] = Integer.MAX_VALUE; 29 | for (int j = 0 ; j < len ; j++) { // check all cities, find the least possible one 30 | int prevOptimal; 31 | if ((i - customers[j]) < 0) { // OUT OF BOUNDS 32 | prevOptimal = 0; 33 | } else { 34 | prevOptimal = minSoln[i - customers[j]]; // minSoln for customers less than i 35 | } 36 | minSoln[i] = Math.min(minSoln[i], prevOptimal + cost[j]); // it is previous optimal soln + this cost 37 | } 38 | } 39 | 40 | return minSoln[minCustomers]; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /13_Misc/TopCoder/src/hotel/HotelTest.java: -------------------------------------------------------------------------------- 1 | package hotel; 2 | 3 | import static org.junit.Assert.*; 4 | 5 | import org.junit.Test; 6 | 7 | import cardStraights.CardStraights; 8 | 9 | /* 10 | 11 | 12 | */ 13 | public class HotelTest { 14 | 15 | @Test 16 | public void testMarketCost1() { 17 | /* 18 | 10 19 | {1,2,3} 20 | {3,2,1} 21 | Returns: 4 22 | Just get 12 customers from the third city. 23 | */ 24 | int minCustomers = 10; 25 | int customers[] = {1,2,3}; 26 | int cost[] = {3,2,1}; 27 | assertEquals(4, Hotel.marketCost(minCustomers, customers, cost)); 28 | } 29 | @Test 30 | public void testMarketCost2() { 31 | /* 32 | 10 33 | {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 34 | {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} 35 | Returns: 10 36 | It does not matter from which city you get your customers. 37 | */ 38 | int minCustomers = 10; 39 | int customers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 40 | int cost[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 41 | assertEquals(10, Hotel.marketCost(minCustomers, customers, cost)); 42 | } 43 | @Test 44 | public void testMarketCost3() { 45 | /* 46 | 12 47 | {5, 1} 48 | {3, 1} 49 | Returns: 8 50 | Get 10 customers from the first city, and 2 from the second city. 51 | */ 52 | int minCustomers = 12; 53 | int customers[] = {5, 1}; 54 | int cost[] = {3, 1}; 55 | assertEquals(1, Hotel.marketCost(1, customers, cost)); 56 | assertEquals(2, Hotel.marketCost(2, customers, cost)); 57 | assertEquals(3, Hotel.marketCost(4, customers, cost)); 58 | assertEquals(8, Hotel.marketCost(minCustomers, customers, cost)); 59 | } 60 | @Test 61 | public void testMarketCost4() { 62 | /* 63 | 100 64 | {9, 11, 4, 7, 2, 8} 65 | {4, 9, 3, 8, 1, 9} 66 | Returns: 45 67 | */ 68 | int minCustomers = 100; 69 | int customers[] = {9, 11, 4, 7, 2, 8}; 70 | int cost[] = {4, 9, 3, 8, 1, 9}; 71 | assertEquals(45, Hotel.marketCost(minCustomers, customers, cost)); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /13_Misc/TopCoder/src/tallPeople/TallPeople.java: -------------------------------------------------------------------------------- 1 | package tallPeople; 2 | 3 | import java.util.Arrays; 4 | // http://community.topcoder.com/stat?c=problem_statement&pm=2923&rd=5854 5 | public class TallPeople { 6 | public static int[] getPeople(String[] people) { //O(RC) 7 | int tallestOfShortest = Integer.MIN_VALUE; // row 8 | int shortestOfTheTallest = Integer.MAX_VALUE; // column 9 | int[] tallest = new int[people[0].split(" ").length]; //O(C) 10 | Arrays.fill(tallest, Integer.MIN_VALUE); 11 | for (String row: people) { //O(R) 12 | int shortest = Integer.MAX_VALUE; 13 | String[] l = row.split(" "); 14 | for (int i=0; i