From 328ca111a5036ba6b23ac61d2145c192c84985a4 Mon Sep 17 00:00:00 2001 From: Pragy Agarwal Date: Tue, 17 Mar 2020 19:17:10 +0530 Subject: [PATCH 1/4] fix oopsie --- DS_implementations/python/disjoint_set.py | 1 + 1 file changed, 1 insertion(+) diff --git a/DS_implementations/python/disjoint_set.py b/DS_implementations/python/disjoint_set.py index d2174c3..f47ebe9 100644 --- a/DS_implementations/python/disjoint_set.py +++ b/DS_implementations/python/disjoint_set.py @@ -38,6 +38,7 @@ class DisjointSet(Generic[T]): Amortized Time Complexity per query: ~O(1) """ x, y = self.find_root(x), self.find_root(y) + if x == y: return # if both x and y are already in the same component, do thing if self.size_of(x) < self.size_of(y): x, y = y, x # swap so that y is always the larger component self._parents[y] = x From 8b4e2428b06f4f71663373968e3a92d62e998385 Mon Sep 17 00:00:00 2001 From: Sanket Singh Date: Tue, 17 Mar 2020 19:42:59 +0530 Subject: [PATCH 2/4] Create Strings.md --- Strings.md | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 Strings.md diff --git a/Strings.md b/Strings.md new file mode 100644 index 0000000..0a141e2 --- /dev/null +++ b/Strings.md @@ -0,0 +1,199 @@ + +**Q1- First Unique Character in a String** + +**Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1.** + +``` +s = "InterviewBit" +return 1. +``` + +_Approach:_ + +The best possible solution here could be of a linear time because to ensure that the character is unique you have to check the whole string anyway. + +The idea is to go through the string and save in a hash map the number of times each character appears in the string. That would take O(N) time, where N is a number of characters in the string. + +And then we go through the string the second time, this time we use the hash map as a reference to check if a character is unique or not. +If the character is unique, one could just return its index. The complexity of the second iteration is O(N) as well. + +``` +public int firstUniqChar(String s) { + HashMap count = new HashMap(); + int n = s.length(); + // build hash map : character and how often it appears + for (int i = 0; i < n; i++) { + char c = s.charAt(i); + count.put(c, count.getOrDefault(c, 0) + 1); + } + + // find the index + for (int i = 0; i < n; i++) { + if (count.get(s.charAt(i)) == 1) + return i; + } + return -1; +} +``` + +Time complexity : O(N) since we go through the string of length N two times. + +Space complexity : O(N) since we have to keep a hash map with N elements. + +**Q2- Isomorphic Strings** + +**Given two strings s and t, determine if they are isomorphic.Two strings are isomorphic if the characters in s can be replaced to get t. All occurrences of a character must be replaced with another character while preserving the order of characters. No two characters may map to the same character but a character may map to itself.** + +``` +Input: s = "egg", t = "add" +Output: true + +Input: s = "foo", t = "bar" +Output: false + +Input: s = "paper", t = "title" +Output: true +``` + +Solution: + +The idea is that we need to map a char to another one, for example, "egg" and "add", we need to constract the mapping 'e' -> 'a' and 'g' -> 'd'. Instead of directly mapping 'e' to 'a', another way is to mark them with same value, for example, 'e' -> 1, 'a'-> 1, and 'g' -> 2, 'd' -> 2, this works same. + +So we use two arrays here m1 and m2, initialized space is 256 (Since the whole ASCII size is 256, 128 also works here). Traverse the character of both s and t on the same position, if their mapping values in m1 and m2 are different, means they are not mapping correctly, returen false; else we construct the mapping, since m1 and m2 are both initialized as 0, we want to use a new value when i == 0, so i + 1 works here. + +https://leetcode.com/problems/isomorphic-strings/discuss/57796/My-6-lines-solution + +https://leetcode.com/problems/isomorphic-strings/discuss/57802/Java-solution-using-HashMap + +**Q3- Valid Anagram** + +**Given two strings s and t , write a function to determine if t is an anagram of s.** + +``` +Input: s = "anagram", t = "nagaram" +Output: true + +Input: s = "rat", t = "car" +Output: false +``` + +https://leetcode.com/problems/valid-anagram/solution/ + +**Q4- Check if a string can be obtained by rotating another string 2 places** + +``` +Input: string1 = “amazon”, string2 = “azonam” +Output: Yes +// rotated anti-clockwise + +Input: string1 = “amazon”, string2 = “onamaz” +Output: Yes +// rotated clockwise +``` + +1- There can be only two cases: + a) Clockwise rotated + b) Anti-clockwise rotated + +2- If clockwise rotated that means elements + are shifted in right. + So, check if a substring[2.... len-1] of + string2 when concatenated with substring[0,1] + of string2 is equal to string1. Then, return true. + +3- Else, check if it is rotated anti-clockwise + that means elements are shifted to left. + So, check if concatenation of substring[len-2, len-1] + with substring[0....len-3] makes it equals to + string1. Then return true. + +4- Else, return false. + +``` +static boolean isRotated(String str1, String str2) + { + if (str1.length() != str2.length()) + return false; + + String clock_rot = ""; + String anticlock_rot = ""; + int len = str2.length(); + + // Initialize string as anti-clockwise rotation + anticlock_rot = anticlock_rot + + str2.substring(len-2, len) + + str2.substring(0, len-2) ; + + // Initialize string as clock wise rotation + clock_rot = clock_rot + + str2.substring(2) + + str2.substring(0, 2) ; + + // check if any of them is equal to string1 + return (str1.equals(clock_rot) || + str1.equals(anticlock_rot)); + } + + +``` +Time Complexity: O(n) + +https://www.geeksforgeeks.org/check-string-can-obtained-rotating-another-string-2-places/ + +Followup Question: + +https://www.geeksforgeeks.org/check-if-a-string-can-be-obtained-by-rotating-another-string-d-places/ + +https://www.geeksforgeeks.org/a-program-to-check-if-strings-are-rotations-of-each-other/ + +**Q5- Given an input string, reverse the string word by word.** + +``` +Input: "the sky is blue" +Output: "blue is sky the" + +Input: " hello world! " +Output: "world! hello" +Explanation: Your reversed string should not contain leading or trailing spaces. +``` + +- A word is defined as a sequence of non-space characters. + +- Input string may contain leading or trailing spaces. However, your reversed string should not contain leading or trailing spaces. + +- You need to reduce multiple spaces between two words to a single space in the reversed string. + +https://leetcode.com/problems/reverse-words-in-a-string/solution/ + +**Q6- String to Integer (atoi)** + +Question: +https://leetcode.com/problems/string-to-integer-atoi/ + +Answer: +https://leetcode.com/problems/string-to-integer-atoi/discuss/4643/Java-Solution-with-4-steps-explanations + +**Q7- Longest Substring Without Repeating Characters** + +**Given a string, find the length of the longest substring without repeating characters.** +``` +Input: "abcabcbb" +Output: 3 +Explanation: The answer is "abc", with the length of 3. + +Input: "pwwkew" +Output: 3 +Explanation: The answer is "wke", with the length of 3. + Note that the answer must be a substring, "pwke" is a subsequence and not a substring. +``` + +https://leetcode.com/problems/longest-substring-without-repeating-characters/solution/ + +**Q8- Longest Duplicate Substring** + +https://leetcode.com/problems/longest-duplicate-substring/ + +**Homework Problem** + +https://codeforces.com/problemset/problem/676/C + From 67e64ba2588c45875be1a1ecaaeea885dcd85318 Mon Sep 17 00:00:00 2001 From: Sanket Singh Date: Tue, 17 Mar 2020 19:52:50 +0530 Subject: [PATCH 3/4] Create Recursion & Backtracking.md --- Recursion & Backtracking.md | 331 ++++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100644 Recursion & Backtracking.md diff --git a/Recursion & Backtracking.md b/Recursion & Backtracking.md new file mode 100644 index 0000000..c84c457 --- /dev/null +++ b/Recursion & Backtracking.md @@ -0,0 +1,331 @@ + +## Recursion + +- Also called Divide n conquer. + +- Better to say reduce and conquer. + +- Assume that smaller problem will work and build solution for larger problem. + +- Solution starts aggregating at base case. + +## Backtracking + +- A) Element of choice + +- B) Explore all possibilities (Solving question in tree like fashion ) + +**Steps for Coding:** + +- Take a decision (When you take a decision, you know that now your problem has been reduced ) + +- Recur (Solving reduced problem ) + +- Undo Decision I + +**Q1 Gray Code** + +The gray code is a binary numeral system where two successive values differ in only one bit. + +Given a non-negative integer n representing the total number of bits in the code, print the sequence of gray code. A gray code sequence must begin with 0. + +**Q2- Word Break** + +Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, add spaces in s to construct a sentence where each word is a valid dictionary word. Return all such possible sentences. + +Note: + +The same word in the dictionary may be reused multiple times in the segmentation. + +You may assume the dictionary does not contain duplicate words. + +``` +Input: +s = "catsanddog" +wordDict = ["cat", "cats", "and", "sand", "dog"] +Output: +[ + "cats and dog", + "cat sand dog" +] +``` + +_Recursion_ + +```java +public List wordBreak(String s, Set wordDict) { + return word_Break(s, wordDict, 0); + } + + public List word_Break(String s, Set wordDict, int start) { + LinkedList res = new LinkedList<>(); + if (start == s.length()) { + res.add(""); + } + for (int end = start + 1; end <= s.length(); end++) { + if (wordDict.contains(s.substring(start, end))) { + List list = word_Break(s, wordDict, end); + for (String l : list) { + res.add(s.substring(start, end) + (l.equals("") ? "" : " ") + l); + } + } + } + return res; + } +``` + +_Recursion with memoization__ +```java + +public List wordBreak(String s, List wordDict) { + return word_break(s, wordDict, 0); + } + + HashMap> map = new HashMap<>(); + + public List word_break(String s, ListwordDict, int start){ + if(map.containsKey(start)){ + return map.get(start); + } + LinkedList res = new LinkedList<>(); + + if(start == s.length()){ + res.add(""); + } + + for(int end = start + 1; end <= s.length(); end++){ + if(wordDict.contains(s.substring(start, end))){ + List list = word_break(s, wordDict, end); + for(String l: list){ + res.add(s.substring(start, end) + (l.equals("") ? "" : " ") + l); + } + } + } + System.out.println(start); + System.out.println(res); + map.put(start, res); + return res; + } +``` + + +**Q3- Generate Paranthesis** + +Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses. + +For example, given n = 3, a solution set is: + +``` +[ + "((()))", + "(()())", + "(())()", + "()(())", + "()()()" +] + +``` + +```java + +public List generateParenthesis(int n) { + + List ans = new ArrayList<>(); + backtrack(ans, "", 0, 0, n); + + return ans; + } + + public void backtrack(List ans, String curr, int open, int close, int max){ + if(curr.length() == max * 2){ + ans.add(curr); + return; + } + + if(open < max){ + backtrack(ans, curr + "(", open + 1, close, max); + } + + if(close < open){ + backtrack(ans, curr + ")", open, close + 1, max); + } + } + +``` + +Time Complexity: + +**Q4- Palindrome Partitioning** + +Given a string s, partition s such that every substring of the partition is a palindrome. + +Print all palindromic partitions. + +Partitioning means that dividing the string into k parts such that: + +1. Maintain order + +2. Mutually exlusive partitions - no overlap of elements + +3. Mutually exhaustive partitions - union of all subsets gets the entire string. + +4. Every partition should be a palindrome + +``` +Input: "aab" + +Output: +[ + ["aa","b"], + ["a","a","b"] +] + +Invalid: +["a", "ab"] + +``` +- Why a backtracking problem? Because you want to find all possible partitions. + +- Element of Choice? Do I introduce a partition after ith element or not? + +- How to represent a state? f(i) + +- At each step, you have two choice, whether to introduce partition not introduce partition. + +- Also at each step, check if the currString till now is palindrome or not. If it is not, we do pruning. + +```java + +public class Solution { + + List> resultLst; + ArrayList currLst; + + public List> partition(String s) { + resultLst = new ArrayList>(); + currLst = new ArrayList(); + backTrack(s,0); + return resultLst; + } + + public void backTrack(String s, int l){ + + if(currLst.size()>0 //the initial str could be palindrome + && l>=s.length()){ + List r = (ArrayList) currLst.clone(); + resultLst.add(r); + } + + for(int i=l;i children; + TrieNode(char ch, bool isTerminal) { + this->ch = ch; + this->isTerminal = isTerminal; + } + +}; +class Solution { +public: + vector result; + void insert(string word, TrieNode *root) { + TrieNode* temp = root; + for(int i = 0; i < word.size(); i++) { + char ch = word[i]; + if(temp->children.find(ch) != temp->children.end()) { + temp = temp->children[ch]; + } else { + temp->children[ch] = new TrieNode(ch, false); + temp = temp->children[ch]; + } + } + temp->isTerminal = true; + return; + } + + + void backtrack(vector>& board, TrieNode* root, int i, int j, bool **visited, string str) { + if(i < 0 or j < 0 or i >= board.size() or j >= board[0].size()) { + return; + } + if(visited[i][j] == true) return; + char ch = board[i][j]; + if(root->children.find(ch) == root->children.end()) { + return; + } else { + root = root->children[ch]; + } + if(root->isTerminal == true) { + result.push_back(str+board[i][j]); + root->isTerminal = false; + } + visited[i][j] = true; + backtrack(board, root, i+1, j, visited, str+board[i][j]); + backtrack(board, root, i-1, j, visited, str+board[i][j]); + backtrack(board, root, i, j+1, visited, str+board[i][j]); + backtrack(board, root, i, j-1, visited, str+board[i][j]); + visited[i][j] = false; + return; + } + + vector findWords(vector>& board, vector& words) { + TrieNode *root = new TrieNode('\0', false); + for(string word: words) { + insert(word, root); + } + bool **visited = new bool*[board.size()]; + for(int i = 0; i < board.size(); i++) { + visited[i] = new bool[board[0].size()](); + } + + for(int i = 0; i < board.size(); i++) { + for(int j = 0; j < board[0].size(); j++) { + TrieNode* temp = root; + backtrack(board, temp, i, j, visited, ""); + } + } + return result; + } +}; + +``` From 475c6573fec3d32a1b6273666b8f0570021f2718 Mon Sep 17 00:00:00 2001 From: Sanket Singh Date: Thu, 19 Mar 2020 12:31:49 +0530 Subject: [PATCH 4/4] Create Stacks.md --- Stacks.md | 218 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 Stacks.md diff --git a/Stacks.md b/Stacks.md new file mode 100644 index 0000000..3fe9cf9 --- /dev/null +++ b/Stacks.md @@ -0,0 +1,218 @@ + +## Stack + +- Abstract Datatype +- Linear data structure +- Sequential Access +- LIFO (Last In First Out) + +### Stack Operations + +- Push +- Pop +### Implementation of Stack + +- Array (Keep the two conditions in mind during interviews) + - Stack Overflow + - Stack Underflow + - **Pros**: Easy to implement. Memory is saved as pointers are not involved. + - **Cons**: It is not dynamic. It doesn’t grow and shrink depending on needs at runtime. + - Can use Vectors/ArrayList also +- LinkedList + - Push() - Add at head. O(1) + - Pop() - Remove at Head. O(1) +- Queue - Will discuss later + +**Q- Given only two operations i.e., push() and pop(), implement insertAtBottom() function** + +Approach 1: Using Extra Stack + +Approach 2: Using Recursion + +```java + +insertAtBotton(Stack s, int n){ + if(s.isEmpty()){ + s.push(n); + } + int temp = s.pop(); + insertAtBottom(s, n); + s.push(temp); +} + +``` + +**Q- Reverse a stack** +(Perform Reversal in same stack) +Approach 1: +```java + +reverse(Stack s){ + if(s.isEmpty()){ + return; + } + int temp = s.pop(); + reverse(s, n); + insertAtBottom(s, temp); +} + +``` + + Time Complexity - + Pushing one element at the bottom - O(n) + Pushing n elements at the bottom - O(n^2) + +Approach 2: Take two auxillary stack + + +**Q- Implement Sorting using stack** +The idea of the solution is to hold all values in Function Call Stack until the stack becomes empty. When the stack becomes empty, insert all held items one by one in sorted order. Here sorted order is important. + +Similar to above question. Just implement insertInSortedWay(). + +```java + +sortStack(stack S) + if stack is not empty: + temp = pop(S); + sortStack(S); + sortedInsert(S, temp); + + + sortedInsert(Stack S, element) + if stack is empty OR element > top element + push(S, elem) + else + temp = pop(S) + sortedInsert(S, element) + push(S, temp) + + ``` + +Time Complexity: O(n^2) +Space Complexity: O(n) + +**Q- Remove consecutive duplicates in a string** +String: kabbal +Output: kl + +**Special case** +String: aaa +Output: a + +Time Complexity: O(string.length) +Space Complexity: O(string.length) + +**Q- Valid Paranthesis** + +Input: "()[]{}" +Output: true + +```java +public boolean isValid(String s) { + Stack st = new Stack<>(); + for(int i = 0 ; i < s.length(); i++) { + char ch = s.charAt(i); + if(ch == '(' || ch == '[' || ch == '{') { + st.push(ch); + } else { + if(st.isEmpty()) return false; + char p = st.peek(); + if(ch == ')' && p != '(') return false; + else if(ch == ']' && p != '[') return false; + else if(ch == '}' && p != '{') return false; + else st.pop(); + } + } + return st.isEmpty(); + } + +``` + +Time Complexity: O(n) +Space Complexity: O(n) + +**Q-- Evaluate Infix Expression** +1. Maintain two stacks, one for integers and one for operators + +```java + //Stack for numbers + Stack numbers = new Stack<>(); + + //Stack for operators + Stack operations = new Stack<>(); + + for(int i=0; i numbers, Stack operations) { + int a = numbers.pop(); + int b = numbers.pop(); + char operation = operations.pop(); + switch (operation) { + case '+': + return a + b; + case '-': + return b - a; + case '*': + return a * b; + case '/': + if (a == 0) + throw new + UnsupportedOperationException("Cannot divide by zero"); + return b / a; + } + return 0; + } + + public boolean isOperator(char c){ + return (c=='+'||c=='-'||c=='/'||c=='*'||c=='^'); + } +``` + +Time Complexity: O(n) +Space Complexity: O(n) + + +