From 062d4fc8507839d1b98e34c64160e685f68bc8ee Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Thu, 15 Aug 2019 13:17:19 +0100 Subject: [PATCH 01/26] Sliding Window Problems: done --- .../leetcode/arrays/ShortestWordDistance.java | 4 +- .../IsomorphicStrings.java | 2 +- .../RepeatedDnaSequence.java | 2 +- .../ShortestWordDistanceII.java | 2 +- .../{maps => hashtables}/TwoSumIII.java | 2 +- ...ngestSubstringWithKDistinctCharacters.java | 23 ++-- ...stSubstringWithoutRepeatingCharacters.java | 128 ++++++++++++++++++ .../slidingwindow/MinimumWindowSubstring.java | 104 ++++++++++++++ 8 files changed, 252 insertions(+), 15 deletions(-) rename src/main/java/com/leetcode/{maps => hashtables}/IsomorphicStrings.java (98%) rename src/main/java/com/leetcode/{maps => hashtables}/RepeatedDnaSequence.java (98%) rename src/main/java/com/leetcode/{maps => hashtables}/ShortestWordDistanceII.java (99%) rename src/main/java/com/leetcode/{maps => hashtables}/TwoSumIII.java (98%) rename src/main/java/com/leetcode/{maps => hashtables}/slidingwindow/LongestSubstringWithKDistinctCharacters.java (78%) create mode 100644 src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithoutRepeatingCharacters.java create mode 100644 src/main/java/com/leetcode/hashtables/slidingwindow/MinimumWindowSubstring.java diff --git a/src/main/java/com/leetcode/arrays/ShortestWordDistance.java b/src/main/java/com/leetcode/arrays/ShortestWordDistance.java index 50b198cd..5cd0c821 100644 --- a/src/main/java/com/leetcode/arrays/ShortestWordDistance.java +++ b/src/main/java/com/leetcode/arrays/ShortestWordDistance.java @@ -1,5 +1,7 @@ package com.leetcode.arrays; +import com.leetcode.hashtables.ShortestWordDistanceII; + import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -16,7 +18,7 @@ * * Note: You may assume that word1 does not equal to word2, and word1 and word2 are both in the list. * - * Lastly, for a more complex variant, see {@link com.leetcode.maps.ShortestWordDistanceII}. + * Lastly, for a more complex variant, see {@link ShortestWordDistanceII}. * * @author rampatra * @since 2019-07-31 diff --git a/src/main/java/com/leetcode/maps/IsomorphicStrings.java b/src/main/java/com/leetcode/hashtables/IsomorphicStrings.java similarity index 98% rename from src/main/java/com/leetcode/maps/IsomorphicStrings.java rename to src/main/java/com/leetcode/hashtables/IsomorphicStrings.java index 78bc02bd..f9a7f4eb 100644 --- a/src/main/java/com/leetcode/maps/IsomorphicStrings.java +++ b/src/main/java/com/leetcode/hashtables/IsomorphicStrings.java @@ -1,4 +1,4 @@ -package com.leetcode.maps; +package com.leetcode.hashtables; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/leetcode/maps/RepeatedDnaSequence.java b/src/main/java/com/leetcode/hashtables/RepeatedDnaSequence.java similarity index 98% rename from src/main/java/com/leetcode/maps/RepeatedDnaSequence.java rename to src/main/java/com/leetcode/hashtables/RepeatedDnaSequence.java index a4eddb4a..7674273d 100644 --- a/src/main/java/com/leetcode/maps/RepeatedDnaSequence.java +++ b/src/main/java/com/leetcode/hashtables/RepeatedDnaSequence.java @@ -1,4 +1,4 @@ -package com.leetcode.maps; +package com.leetcode.hashtables; import java.util.*; diff --git a/src/main/java/com/leetcode/maps/ShortestWordDistanceII.java b/src/main/java/com/leetcode/hashtables/ShortestWordDistanceII.java similarity index 99% rename from src/main/java/com/leetcode/maps/ShortestWordDistanceII.java rename to src/main/java/com/leetcode/hashtables/ShortestWordDistanceII.java index ecb6c9b9..3932cebf 100644 --- a/src/main/java/com/leetcode/maps/ShortestWordDistanceII.java +++ b/src/main/java/com/leetcode/hashtables/ShortestWordDistanceII.java @@ -1,4 +1,4 @@ -package com.leetcode.maps; +package com.leetcode.hashtables; import java.util.ArrayList; import java.util.HashMap; diff --git a/src/main/java/com/leetcode/maps/TwoSumIII.java b/src/main/java/com/leetcode/hashtables/TwoSumIII.java similarity index 98% rename from src/main/java/com/leetcode/maps/TwoSumIII.java rename to src/main/java/com/leetcode/hashtables/TwoSumIII.java index 22f0748f..88916db0 100644 --- a/src/main/java/com/leetcode/maps/TwoSumIII.java +++ b/src/main/java/com/leetcode/hashtables/TwoSumIII.java @@ -1,4 +1,4 @@ -package com.leetcode.maps; +package com.leetcode.hashtables; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/leetcode/maps/slidingwindow/LongestSubstringWithKDistinctCharacters.java b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java similarity index 78% rename from src/main/java/com/leetcode/maps/slidingwindow/LongestSubstringWithKDistinctCharacters.java rename to src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java index 21cfab23..84a0773c 100644 --- a/src/main/java/com/leetcode/maps/slidingwindow/LongestSubstringWithKDistinctCharacters.java +++ b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java @@ -1,4 +1,4 @@ -package com.leetcode.maps.slidingwindow; +package com.leetcode.hashtables.slidingwindow; import java.util.HashMap; import java.util.Map; @@ -38,11 +38,11 @@ public static int lengthOfLongestSubstringKDistinct(String str, int k) { int length = 0; Map letterCountInWindow = new HashMap<>(); - int i = 0; // start of window - int j = i; // end of window + int left = 0; // start of window + int right = 0; // end of window - while (j < str.length()) { - char ch = str.charAt(j); + while (right < str.length()) { + char ch = str.charAt(right); letterCountInWindow.put(ch, letterCountInWindow.getOrDefault(ch, 0) + 1); @@ -51,20 +51,20 @@ public static int lengthOfLongestSubstringKDistinct(String str, int k) { // - remove the first character in the window or reduce its count if the window had more than one of this character // - lastly, move the window forward if (letterCountInWindow.keySet().size() > k) { - char firstChar = str.charAt(i); + char firstChar = str.charAt(left); int firstCharCount = letterCountInWindow.get(firstChar); if (firstCharCount > 1) { letterCountInWindow.put(firstChar, firstCharCount - 1); } else { letterCountInWindow.remove(firstChar); } - length = Math.max(length, j - i); - i++; + length = Math.max(length, right - left); + left++; } - j++; + right++; } - return length == 0 ? j - i : length; + return length == 0 ? right - left : length; } public static void main(String[] args) { @@ -75,5 +75,8 @@ public static void main(String[] args) { assertEquals(2, lengthOfLongestSubstringKDistinct("aa", 1)); assertEquals(3, lengthOfLongestSubstringKDistinct("aaa", 1)); assertEquals(0, lengthOfLongestSubstringKDistinct("aa", 0)); + assertEquals(3, lengthOfLongestSubstringKDistinct("aab", 2)); + assertEquals(8, lengthOfLongestSubstringKDistinct("abcabcbb", 3)); + assertEquals(5, lengthOfLongestSubstringKDistinct("pwwkew", 3)); } } diff --git a/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithoutRepeatingCharacters.java b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithoutRepeatingCharacters.java new file mode 100644 index 00000000..93a940e4 --- /dev/null +++ b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithoutRepeatingCharacters.java @@ -0,0 +1,128 @@ +package com.leetcode.hashtables.slidingwindow; + +import java.util.HashSet; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Medium + * Link: https://leetcode.com/problems/longest-substring-without-repeating-characters/ + * Description: + * Given a string, find the length of the longest substring without repeating characters. + *

+ * Example 1: + * Input: "abcabcbb" + * Output: 3 + * Explanation: The answer is "abc", with the length of 3. + *

+ * Example 2: + * Input: "bbbbb" + * Output: 1 + * Explanation: The answer is "b", with the length of 1. + *

+ * Example 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. + * + * @author rampatra + * @since 2019-08-15 + */ +public class LongestSubstringWithoutRepeatingCharacters { + + /** + * Sliding Window Approach (using map). + *

+ * Note: + * If we know that the charset is rather small, we can replace the Map with an integer array as direct access table. + *

+ * Commonly used tables are: + *

+ * int[26] for Letters 'a' - 'z' or 'A' - 'Z' + * int[128] for ASCII + * int[256] for Extended ASCII + *

+ * Runtime: 8 ms. + * + * @param s + * @return + */ + public static int lengthOfLongestSubstring(String s) { + int left = 0; + int right = 0; + int longestSubstringLen = 0; + Set charsInWindow = new HashSet<>(); + + + while (right < s.length()) { + + if (charsInWindow.contains(s.charAt(right))) { + while (s.charAt(left) != s.charAt(right)) { + longestSubstringLen = Math.max(longestSubstringLen, right - left); + charsInWindow.remove(s.charAt(left)); + left++; + } + left++; + } + + charsInWindow.add(s.charAt(right)); + right++; + } + + return Math.max(longestSubstringLen, right - left); + } + + /** + * Sliding Window Approach using int array. + * + * Runtime: 2 ms. + * + * @param s + * @return + */ + public static int lengthOfLongestSubstringNoMap(String s) { + int left = 0; + int right = 0; + int longestSubstringLen = 0; + int[] charsInWindow = new int[128]; + + // keep moving forward the right pointer and adding characters to the window + while (right < s.length()) { + + // once we encounter repeated characters, move the left pointer until the repeated character is removed + if (charsInWindow[s.charAt(right)] == 1) { + while (s.charAt(left) != s.charAt(right)) { + longestSubstringLen = Math.max(longestSubstringLen, right - left); + charsInWindow[s.charAt(left)] = 0; + left++; + } + left++; + } + + charsInWindow[s.charAt(right)] = 1; + right++; + } + + return Math.max(longestSubstringLen, right - left); + } + + public static void main(String[] args) { + assertEquals(0, lengthOfLongestSubstring("")); + assertEquals(1, lengthOfLongestSubstring(" ")); + assertEquals(1, lengthOfLongestSubstring("a")); + assertEquals(2, lengthOfLongestSubstring("aab")); + assertEquals(3, lengthOfLongestSubstring("abcabcbb")); + assertEquals(1, lengthOfLongestSubstring("bbbbb")); + assertEquals(3, lengthOfLongestSubstring("pwwkew")); + + assertEquals(0, lengthOfLongestSubstringNoMap("")); + assertEquals(1, lengthOfLongestSubstringNoMap(" ")); + assertEquals(1, lengthOfLongestSubstringNoMap("a")); + assertEquals(2, lengthOfLongestSubstringNoMap("aab")); + assertEquals(3, lengthOfLongestSubstringNoMap("abcabcbb")); + assertEquals(1, lengthOfLongestSubstringNoMap("bbbbb")); + assertEquals(3, lengthOfLongestSubstringNoMap("pwwkew")); + } +} \ No newline at end of file diff --git a/src/main/java/com/leetcode/hashtables/slidingwindow/MinimumWindowSubstring.java b/src/main/java/com/leetcode/hashtables/slidingwindow/MinimumWindowSubstring.java new file mode 100644 index 00000000..5414cdc1 --- /dev/null +++ b/src/main/java/com/leetcode/hashtables/slidingwindow/MinimumWindowSubstring.java @@ -0,0 +1,104 @@ +package com.leetcode.hashtables.slidingwindow; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Hard + * Link: https://leetcode.com/problems/minimum-window-substring/ + * Description: + * Given a string S and a string T, find the minimum window in S which will contain all the characters in T in + * complexity O(n). + *

+ * Example: + *

+ * Input: S = "ADOBECODEBANC", T = "ABC" + * Output: "BANC" + *

+ * Note: + * - If there is no such window in S that covers all characters in T, return the empty string "". + * - If there is such window, you are guaranteed that there will always be only one unique minimum window in S. + * + * @author rampatra + * @since 2019-08-13 + */ +public class MinimumWindowSubstring { + + /** + * Sliding Window Approach (using map). + * + * Note: + * If we know that the charset is rather small, we can replace the Map with an integer array as direct access table. + * + * Commonly used tables are: + * + * int[26] for Letters 'a' - 'z' or 'A' - 'Z' + * int[128] for ASCII + * int[256] for Extended ASCII + * + * Runtime: 22 ms. + * + * @param s + * @param t + * @return + */ + public static String minWindow(String s, String t) { + + int left = 0; // start of window + int right = 0; // end of window + int begin = 0; + int windowSize = Integer.MAX_VALUE; + int charsInWindow = 0; // to check whether the window has all the characters in t with the required frequency + + // characters and their counts in t + Map dictT = new HashMap<>(); + for (int i = 0; i < t.length(); i++) { + char ch = t.charAt(i); + dictT.put(ch, dictT.getOrDefault(ch, 0) + 1); + } + + // characters and their counts in the window + Map dictWindow = new HashMap<>(); + + while (right < s.length()) { + char rightChar = s.charAt(right); + int rightCharCount; + dictWindow.put(rightChar, (rightCharCount = dictWindow.getOrDefault(rightChar, 0) + 1)); + + // once the window has a character in t with the required frequency, increment charsInWindow + if (dictT.get(rightChar) != null && dictT.get(rightChar).equals(rightCharCount)) { + charsInWindow++; + } + + // once the window has all characters in t with required frequency then shorten the window by moving the + // left window forward until the window no longer has all characters of t + while (left <= right && charsInWindow == dictT.size()) { + if (right - left < windowSize) { + windowSize = right - left + 1; + begin = left; + } + + char leftChar = s.charAt(left); + Integer leftCharCount = dictWindow.get(leftChar); + dictWindow.put(leftChar, leftCharCount - 1); + + if (dictT.get(leftChar) != null && leftCharCount - 1 < dictT.get(leftChar)) { + charsInWindow--; + } + left++; + } + right++; + } + + return windowSize == Integer.MAX_VALUE ? "" : s.substring(begin, begin + windowSize); + } + + public static void main(String[] args) { + assertEquals("BANC", minWindow("ADOBECODEBANC", "ABC")); + assertEquals("BAC", minWindow("ADOBECODEBAC", "ABC")); + assertEquals("ba", minWindow("bba", "ab")); + assertEquals("baca", minWindow("acbbaca", "aba")); + } +} \ No newline at end of file From 91d26d43c27f4cce4997282be650c0b697d6022a Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Thu, 15 Aug 2019 13:58:00 +0100 Subject: [PATCH 02/26] Minor fix --- .../LongestSubstringWithKDistinctCharacters.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java index 84a0773c..4b209b6e 100644 --- a/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java +++ b/src/main/java/com/leetcode/hashtables/slidingwindow/LongestSubstringWithKDistinctCharacters.java @@ -48,7 +48,7 @@ public static int lengthOfLongestSubstringKDistinct(String str, int k) { // when number of distinct characters in the window exceeds k: // - update length - // - remove the first character in the window or reduce its count if the window had more than one of this character + // - remove the first character in the window or reduce its count if the window has more than one of this character // - lastly, move the window forward if (letterCountInWindow.keySet().size() > k) { char firstChar = str.charAt(left); @@ -64,17 +64,18 @@ public static int lengthOfLongestSubstringKDistinct(String str, int k) { right++; } - return length == 0 ? right - left : length; + return Math.max(length, right - left); } public static void main(String[] args) { assertEquals(3, lengthOfLongestSubstringKDistinct("eceba", 2)); assertEquals(7, lengthOfLongestSubstringKDistinct("eceeeeeba", 2)); + assertEquals(12, lengthOfLongestSubstringKDistinct("bbbeeeeebaaaaaaaaaaa", 2)); assertEquals(2, lengthOfLongestSubstringKDistinct("abcdef", 2)); assertEquals(1, lengthOfLongestSubstringKDistinct("a", 1)); + assertEquals(0, lengthOfLongestSubstringKDistinct("aa", 0)); assertEquals(2, lengthOfLongestSubstringKDistinct("aa", 1)); assertEquals(3, lengthOfLongestSubstringKDistinct("aaa", 1)); - assertEquals(0, lengthOfLongestSubstringKDistinct("aa", 0)); assertEquals(3, lengthOfLongestSubstringKDistinct("aab", 2)); assertEquals(8, lengthOfLongestSubstringKDistinct("abcabcbb", 3)); assertEquals(5, lengthOfLongestSubstringKDistinct("pwwkew", 3)); From 178347086db6101316231e454367a82366c8a214 Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Thu, 15 Aug 2019 20:59:02 +0100 Subject: [PATCH 03/26] Word Ladder I: Done --- .../java/com/leetcode/graphs/WordLadder.java | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/main/java/com/leetcode/graphs/WordLadder.java diff --git a/src/main/java/com/leetcode/graphs/WordLadder.java b/src/main/java/com/leetcode/graphs/WordLadder.java new file mode 100644 index 00000000..78a76920 --- /dev/null +++ b/src/main/java/com/leetcode/graphs/WordLadder.java @@ -0,0 +1,109 @@ +package com.leetcode.graphs; + + +import javafx.util.Pair; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Medium + * Link: https://leetcode.com/problems/word-ladder/ + * Description: + * Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation + * sequence from beginWord to endWord, such that: + *

+ * Only one letter can be changed at a time. Each transformed word must exist in the word list. Note that beginWord + * is not a transformed word. + *

+ * Note: + * - Return 0 if there is no such transformation sequence. + * - All words have the same length. + * - All words contain only lowercase alphabetic characters. + * - You may assume no duplicates in the word list. + * - You may assume beginWord and endWord are non-empty and are not the same. + *

+ * Example 1: + * Input: + * beginWord = "hit", + * endWord = "cog", + * wordList = ["hot","dot","dog","lot","log","cog"] + *

+ * Output: 5 + *

+ * Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog", + * return its length 5. + *

+ * Example 2: + * Input: + * beginWord = "hit" + * endWord = "cog" + * wordList = ["hot","dot","dog","lot","log"] + *

+ * Output: 0 + *

+ * Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. + * + * @author rampatra + * @since 2019-08-15 + */ +public class WordLadder { + + /** + * Runtime: 78 ms. + * + * @param beginWord + * @param endWord + * @param wordList + * @return + */ + public static int ladderLength(String beginWord, String endWord, List wordList) { + int L = beginWord.length(); + Map> originalToTransformedWordMap = new HashMap<>(); + Queue> queue = new LinkedList<>(); + + wordList.forEach(word -> { + String transformedWord; + for (int i = 0; i < L; i++) { + transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L); + originalToTransformedWordMap.putIfAbsent(transformedWord, new HashSet<>()); + originalToTransformedWordMap.get(transformedWord).add(word); + } + } + ); + + Set visited = new HashSet<>(); + queue.add(new Pair<>(beginWord, 1)); + visited.add(beginWord); + + while (!queue.isEmpty()) { + Pair currPair = queue.poll(); + String word = currPair.getKey(); + Integer level = currPair.getValue(); + + if (word.equals(endWord)) { + return level; + } + + String transformedWord; + for (int i = 0; i < L; i++) { + transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L); + + for (String originalWord : originalToTransformedWordMap.getOrDefault(transformedWord, Collections.emptySet())) { + if (!visited.contains(originalWord)) { + queue.add(new Pair<>(originalWord, level + 1)); + visited.add(originalWord); + } + } + } + } + + return 0; + } + + public static void main(String[] args) { + assertEquals(5, ladderLength("hit", "cog", Arrays.asList("hot", "dot", "dog", "lot", "log", "cog"))); + assertEquals(0, ladderLength("hit", "cog", Arrays.asList("hot", "dot", "dog", "lot", "log"))); + } +} From d52dbe74aa77f76f1d3c1a29184293a9eeddaa38 Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Sat, 17 Aug 2019 13:06:15 +0100 Subject: [PATCH 04/26] word ladder done --- src/main/java/com/leetcode/design/AllOne.java | 125 ++++++++++++++ .../java/com/leetcode/graphs/WordLadder.java | 10 +- .../com/leetcode/graphs/WordLadderII.java | 152 ++++++++++++++++++ 3 files changed, 282 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/leetcode/design/AllOne.java create mode 100644 src/main/java/com/leetcode/graphs/WordLadderII.java diff --git a/src/main/java/com/leetcode/design/AllOne.java b/src/main/java/com/leetcode/design/AllOne.java new file mode 100644 index 00000000..51f771d7 --- /dev/null +++ b/src/main/java/com/leetcode/design/AllOne.java @@ -0,0 +1,125 @@ +package com.leetcode.design; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Hard + * Link: https://leetcode.com/problems/all-oone-data-structure/ + * Description: + * Implement a data structure supporting the following operations: + * Inc(Key) - Inserts a new key with value 1. Or increments an existing key by 1. Key is guaranteed to be a non-empty + * string. + * Dec(Key) - If Key's value is 1, remove it from the data structure. Otherwise decrements an existing key by 1. If + * the key does not exist, this function does nothing. Key is guaranteed to be a non-empty string. + * GetMaxKey() - Returns one of the keys with maximal value. If no element exists, return an empty string "". + * GetMinKey() - Returns one of the keys with minimal value. If no element exists, return an empty string "". + *

+ * Challenge: Perform all these in O(1) time complexity. + * + * @author rampatra + * @since 2019-08-11 + */ +public class AllOne { + + + + Map keyToValMap; + Map> valToKeyMap; + + /** + * Initialize your data structure here. + */ + public AllOne() { + keyToValMap = new HashMap<>(); + valToKeyMap = new HashMap<>(); + } + + /** + * Inserts a new key with value 1. Or increments an existing key by 1. + */ + public void inc(String key) { + + } + + /** + * Decrements an existing key by 1. If Key's value is 1, remove it from the data structure. + */ + public void dec(String key) { + + } + + /** + * Returns one of the keys with maximal value. + */ + public String getMaxKey() { + return null; + } + + /** + * Returns one of the keys with Minimal value. + */ + public String getMinKey() { + return null; + } + + public static void main(String[] args) { + AllOne allOne = new AllOne(); + allOne.inc("r"); + allOne.inc("r"); + allOne.dec("r"); + allOne.inc("a"); + allOne.inc("b"); + allOne.inc("b"); + assertEquals("b", allOne.getMaxKey()); + assertEquals("a", allOne.getMinKey()); + + allOne = new AllOne(); + allOne.dec("hello"); + assertEquals("", allOne.getMaxKey()); + + allOne = new AllOne(); + allOne.inc("a"); + allOne.inc("b"); + allOne.inc("b"); + allOne.inc("b"); + allOne.inc("b"); + allOne.dec("b"); + allOne.dec("b"); + assertEquals("b", allOne.getMaxKey()); + assertEquals("a", allOne.getMinKey()); + + allOne = new AllOne(); + allOne.inc("hello"); + allOne.inc("hello"); + assertEquals("hello", allOne.getMaxKey()); + assertEquals("hello", allOne.getMinKey()); + allOne.inc("leet"); + assertEquals("hello", allOne.getMaxKey()); + assertEquals("leet", allOne.getMinKey()); + + allOne = new AllOne(); + allOne.inc("a"); + allOne.inc("b"); + allOne.inc("b"); + allOne.inc("c"); + allOne.inc("c"); + allOne.inc("c"); + allOne.dec("b"); + allOne.dec("b"); + assertEquals("a", allOne.getMinKey()); + allOne.dec("a"); + assertEquals("c", allOne.getMaxKey()); + //assertEquals("c", allOne.getMinKey()); + + allOne = new AllOne(); + allOne.inc("hello"); + allOne.dec("hello"); + assertEquals("", allOne.getMaxKey()); + assertEquals("", allOne.getMinKey()); + } +} \ No newline at end of file diff --git a/src/main/java/com/leetcode/graphs/WordLadder.java b/src/main/java/com/leetcode/graphs/WordLadder.java index 78a76920..979fb12e 100644 --- a/src/main/java/com/leetcode/graphs/WordLadder.java +++ b/src/main/java/com/leetcode/graphs/WordLadder.java @@ -51,7 +51,7 @@ public class WordLadder { /** - * Runtime: 78 ms. + * Runtime: 79 ms. * * @param beginWord * @param endWord @@ -60,15 +60,15 @@ public class WordLadder { */ public static int ladderLength(String beginWord, String endWord, List wordList) { int L = beginWord.length(); - Map> originalToTransformedWordMap = new HashMap<>(); + Map> transformedToOriginalWordMap = new HashMap<>(); Queue> queue = new LinkedList<>(); wordList.forEach(word -> { String transformedWord; for (int i = 0; i < L; i++) { transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L); - originalToTransformedWordMap.putIfAbsent(transformedWord, new HashSet<>()); - originalToTransformedWordMap.get(transformedWord).add(word); + transformedToOriginalWordMap.putIfAbsent(transformedWord, new HashSet<>()); + transformedToOriginalWordMap.get(transformedWord).add(word); } } ); @@ -90,7 +90,7 @@ public static int ladderLength(String beginWord, String endWord, List wo for (int i = 0; i < L; i++) { transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L); - for (String originalWord : originalToTransformedWordMap.getOrDefault(transformedWord, Collections.emptySet())) { + for (String originalWord : transformedToOriginalWordMap.getOrDefault(transformedWord, Collections.emptySet())) { if (!visited.contains(originalWord)) { queue.add(new Pair<>(originalWord, level + 1)); visited.add(originalWord); diff --git a/src/main/java/com/leetcode/graphs/WordLadderII.java b/src/main/java/com/leetcode/graphs/WordLadderII.java new file mode 100644 index 00000000..8265c259 --- /dev/null +++ b/src/main/java/com/leetcode/graphs/WordLadderII.java @@ -0,0 +1,152 @@ +package com.leetcode.graphs; + +import javafx.util.Pair; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Hard + * Link: https://leetcode.com/problems/word-ladder-ii/ + * Description: + * Given two words (beginWord and endWord), and a dictionary's word list, find all shortest transformation sequence(s) + * from beginWord to endWord, such that: + *

+ * Only one letter can be changed at a time + * Each transformed word must exist in the word list. Note that beginWord is not a transformed word. + *

+ * Note: + * - Return an empty list if there is no such transformation sequence. + * - All words have the same length. + * - All words contain only lowercase alphabetic characters. + * - You may assume no duplicates in the word list. + * - You may assume beginWord and endWord are non-empty and are not the same. + *

+ * Example 1: + * Input: + * beginWord = "hit", + * endWord = "cog", + * wordList = ["hot","dot","dog","lot","log","cog"] + *

+ * Output: + * [ + * ["hit","hot","dot","dog","cog"], + * ["hit","hot","lot","log","cog"] + * ] + *

+ *

+ * Example 2: + * Input: + * beginWord = "hit" + * endWord = "cog" + * wordList = ["hot","dot","dog","lot","log"] + *

+ * Output: [] + * Explanation: The endWord "cog" is not in wordList, therefore no possible transformation. + * + * @author rampatra + * @since 2019-08-15 + */ +public class WordLadderII { + + /** + * The approach is same as {@link WordLadder}. We calculate the {@code minDistance} from start to end word and also + * keep a map of words and its adjacent words (i.e, with only character difference). After we are done calculating + * the {@code mindistance}, we perform a dfs on the map upto depth {@code minDistance} and if the last word at this + * depth is equal to the end word then we add all words to the result. + * + * @param beginWord + * @param endWord + * @param wordList + * @return + */ + public static List> findLadders(String beginWord, String endWord, List wordList) { + int L = beginWord.length(); + List> ladders = new LinkedList<>(); + Map> transformedToOriginalWordMap = new HashMap<>(); + Queue> queue = new LinkedList<>(); + + wordList.forEach(word -> { + String transformedWord; + for (int i = 0; i < L; i++) { + transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L); + transformedToOriginalWordMap.putIfAbsent(transformedWord, new HashSet<>()); + transformedToOriginalWordMap.get(transformedWord).add(word); + } + } + ); + + int minDistance = -1; + Set visited = new HashSet<>(); + queue.add(new Pair<>(beginWord, 1)); + visited.add(beginWord); + + HashMap> connectedNodes = new HashMap<>(); + + while (!queue.isEmpty()) { + Pair currPair = queue.poll(); + String word = currPair.getKey(); + Integer level = currPair.getValue(); + + if (word.equals(endWord) && minDistance == -1) { + minDistance = level - 1; + } + + String transformedWord; + for (int i = 0; i < L; i++) { + transformedWord = word.substring(0, i) + "*" + word.substring(i + 1, L); + + for (String originalWord : transformedToOriginalWordMap.getOrDefault(transformedWord, Collections.emptySet())) { + if (!visited.contains(originalWord)) { + queue.add(new Pair<>(originalWord, level + 1)); + visited.add(originalWord); + } + + if (!word.equals(originalWord)) { + connectedNodes.putIfAbsent(word, new HashSet<>()); + connectedNodes.get(word).add(originalWord); + } + } + } + } + + dfs(ladders, new LinkedHashSet<>(), connectedNodes, beginWord, endWord, 0, minDistance); + + return ladders; + } + + /** + * Perform dfs on the map which contains words and its adjacent words. + * + * @param ladders + * @param ladder + * @param connectedNodes + * @param startNode + * @param endNode + * @param distance + * @param minDistance + */ + private static void dfs(List> ladders, Set ladder, Map> connectedNodes, + String startNode, String endNode, int distance, int minDistance) { + if (distance == minDistance && startNode.equals(endNode)) { + ladder.add(endNode); + ladders.add(new ArrayList<>(ladder)); + return; + } else if (distance > minDistance) { + return; + } + + ladder.add(startNode); + for (String nextNode : connectedNodes.getOrDefault(startNode, new HashSet<>())) { + if (!ladder.contains(nextNode)) { + dfs(ladders, new LinkedHashSet<>(ladder), connectedNodes, nextNode, endNode, distance + 1, minDistance); + } + } + } + + public static void main(String[] args) { + assertEquals("[[hit, hot, lot, log, cog], [hit, hot, dot, dog, cog]]", findLadders("hit", "cog", Arrays.asList("hot", "dot", "dog", "lot", "log", "cog")).toString()); + // TODO Fix this test case System.out.println(findLadders("cet", "ism", Arrays.asList("kid", "tag", "pup", "ail", "tun", "woo", "erg", "luz", "brr", "gay", "sip", "kay", "per", "val", "mes", "ohs", "now", "boa", "cet", "pal", "bar", "die", "war", "hay", "eco", "pub", "lob", "rue", "fry", "lit", "rex", "jan", "cot", "bid", "ali", "pay", "col", "gum", "ger", "row", "won", "dan", "rum", "fad", "tut", "sag", "yip", "sui", "ark", "has", "zip", "fez", "own", "ump", "dis", "ads", "max", "jaw", "out", "btu", "ana", "gap", "cry", "led", "abe", "box", "ore", "pig", "fie", "toy", "fat", "cal", "lie", "noh", "sew", "ono", "tam", "flu", "mgm", "ply", "awe", "pry", "tit", "tie", "yet", "too", "tax", "jim", "san", "pan", "map", "ski", "ova", "wed", "non", "wac", "nut", "why", "bye", "lye", "oct", "old", "fin", "feb", "chi", "sap", "owl", "log", "tod", "dot", "bow", "fob", "for", "joe", "ivy", "fan", "age", "fax", "hip", "jib", "mel", "hus", "sob", "ifs", "tab", "ara", "dab", "jag", "jar", "arm", "lot", "tom", "sax", "tex", "yum", "pei", "wen", "wry", "ire", "irk", "far", "mew", "wit", "doe", "gas", "rte", "ian", "pot", "ask", "wag", "hag", "amy", "nag", "ron", "soy", "gin", "don", "tug", "fay", "vic", "boo", "nam", "ave", "buy", "sop", "but", "orb", "fen", "paw", "his", "sub", "bob", "yea", "oft", "inn", "rod", "yam", "pew", "web", "hod", "hun", "gyp", "wei", "wis", "rob", "gad", "pie", "mon", "dog", "bib", "rub", "ere", "dig", "era", "cat", "fox", "bee", "mod", "day", "apr", "vie", "nev", "jam", "pam", "new", "aye", "ani", "and", "ibm", "yap", "can", "pyx", "tar", "kin", "fog", "hum", "pip", "cup", "dye", "lyx", "jog", "nun", "par", "wan", "fey", "bus", "oak", "bad", "ats", "set", "qom", "vat", "eat", "pus", "rev", "axe", "ion", "six", "ila", "lao", "mom", "mas", "pro", "few", "opt", "poe", "art", "ash", "oar", "cap", "lop", "may", "shy", "rid", "bat", "sum", "rim", "fee", "bmw", "sky", "maj", "hue", "thy", "ava", "rap", "den", "fla", "auk", "cox", "ibo", "hey", "saw", "vim", "sec", "ltd", "you", "its", "tat", "dew", "eva", "tog", "ram", "let", "see", "zit", "maw", "nix", "ate", "gig", "rep", "owe", "ind", "hog", "eve", "sam", "zoo", "any", "dow", "cod", "bed", "vet", "ham", "sis", "hex", "via", "fir", "nod", "mao", "aug", "mum", "hoe", "bah", "hal", "keg", "hew", "zed", "tow", "gog", "ass", "dem", "who", "bet", "gos", "son", "ear", "spy", "kit", "boy", "due", "sen", "oaf", "mix", "hep", "fur", "ada", "bin", "nil", "mia", "ewe", "hit", "fix", "sad", "rib", "eye", "hop", "haw", "wax", "mid", "tad", "ken", "wad", "rye", "pap", "bog", "gut", "ito", "woe", "our", "ado", "sin", "mad", "ray", "hon", "roy", "dip", "hen", "iva", "lug", "asp", "hui", "yak", "bay", "poi", "yep", "bun", "try", "lad", "elm", "nat", "wyo", "gym", "dug", "toe", "dee", "wig", "sly", "rip", "geo", "cog", "pas", "zen", "odd", "nan", "lay", "pod", "fit", "hem", "joy", "bum", "rio", "yon", "dec", "leg", "put", "sue", "dim", "pet", "yaw", "nub", "bit", "bur", "sid", "sun", "oil", "red", "doc", "moe", "caw", "eel", "dix", "cub", "end", "gem", "off", "yew", "hug", "pop", "tub", "sgt", "lid", "pun", "ton", "sol", "din", "yup", "jab", "pea", "bug", "gag", "mil", "jig", "hub", "low", "did", "tin", "get", "gte", "sox", "lei", "mig", "fig", "lon", "use", "ban", "flo", "nov", "jut", "bag", "mir", "sty", "lap", "two", "ins", "con", "ant", "net", "tux", "ode", "stu", "mug", "cad", "nap", "gun", "fop", "tot", "sow", "sal", "sic", "ted", "wot", "del", "imp", "cob", "way", "ann", "tan", "mci", "job", "wet", "ism", "err", "him", "all", "pad", "hah", "hie", "aim", "ike", "jed", "ego", "mac", "baa", "min", "com", "ill", "was", "cab", "ago", "ina", "big", "ilk", "gal", "tap", "duh", "ola", "ran", "lab", "top", "gob", "hot", "ora", "tia", "kip", "han", "met", "hut", "she", "sac", "fed", "goo", "tee", "ell", "not", "act", "gil", "rut", "ala", "ape", "rig", "cid", "god", "duo", "lin", "aid", "gel", "awl", "lag", "elf", "liz", "ref", "aha", "fib", "oho", "tho", "her", "nor", "ace", "adz", "fun", "ned", "coo", "win", "tao", "coy", "van", "man", "pit", "guy", "foe", "hid", "mai", "sup", "jay", "hob", "mow", "jot", "are", "pol", "arc", "lax", "aft", "alb", "len", "air", "pug", "pox", "vow", "got", "meg", "zoe", "amp", "ale", "bud", "gee", "pin", "dun", "pat", "ten", "mob"))); + } +} From 3e95cdc9352111af0a408ae6b2c6b023c02001fa Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Sat, 17 Aug 2019 19:31:05 +0100 Subject: [PATCH 05/26] IsomorphicStrings: done --- .../java/com/leetcode/graphs/WordLadder.java | 14 +- .../trees/SerializeDeserializeBinaryTree.java | 179 ++++++++++++++++++ 2 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/leetcode/trees/SerializeDeserializeBinaryTree.java diff --git a/src/main/java/com/leetcode/graphs/WordLadder.java b/src/main/java/com/leetcode/graphs/WordLadder.java index 979fb12e..61e706ce 100644 --- a/src/main/java/com/leetcode/graphs/WordLadder.java +++ b/src/main/java/com/leetcode/graphs/WordLadder.java @@ -102,8 +102,20 @@ public static int ladderLength(String beginWord, String endWord, List wo return 0; } + /** + * TODO: Optimized both end BFS solution + * + * @param beginWord + * @param endWord + * @param wordList + * @return + */ + public static int ladderLengthOptimized(String beginWord, String endWord, List wordList) { + return -1; + } + public static void main(String[] args) { assertEquals(5, ladderLength("hit", "cog", Arrays.asList("hot", "dot", "dog", "lot", "log", "cog"))); assertEquals(0, ladderLength("hit", "cog", Arrays.asList("hot", "dot", "dog", "lot", "log"))); } -} +} \ No newline at end of file diff --git a/src/main/java/com/leetcode/trees/SerializeDeserializeBinaryTree.java b/src/main/java/com/leetcode/trees/SerializeDeserializeBinaryTree.java new file mode 100644 index 00000000..690de39d --- /dev/null +++ b/src/main/java/com/leetcode/trees/SerializeDeserializeBinaryTree.java @@ -0,0 +1,179 @@ +package com.leetcode.trees; + + +import java.util.LinkedList; +import java.util.Queue; + +/** + * Level: Hard + * Link: https://leetcode.com/problems/serialize-and-deserialize-binary-tree/ + * Description: + * Serialization is the process of converting a data structure or object into a sequence of bits so that it can be + * stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in + * the same or another computer environment. + * + * Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your + * serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized + * to a string and this string can be deserialized to the original tree structure. + * + * Example: + * + * You may serialize the following tree: + * + * 1 + * / \ + * 2 3 + * / \ + * 4 5 + * + * as "[1,2,3,null,null,4,5]" + * + * Clarification: The above format is the same as how LeetCode serializes a binary tree. You do not necessarily need + * to follow this format, so please be creative and come up with different approaches yourself. + * + * Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms + * should be stateless. + * + * @author rampatra + * @since 2019-08-17 + */ +public class SerializeDeserializeBinaryTree { + + /** + * Runtime: 31 ms. + * + * @param root + * @return + */ + public static String serialize(TreeNode root) { + if (root == null) { + return "[]"; + } + + StringBuilder sb = new StringBuilder(); + sb.append("["); + + Queue queue = new LinkedList<>(); + queue.add(root); + + while (!queue.isEmpty()) { + TreeNode node = queue.poll(); + + if (sb.length() > 1) { + sb.append(", "); + } + if (node == null) { + sb.append("null"); + continue; + } + + sb.append(node.val); + + queue.add(node.left); + queue.add(node.right); + } + + sb.append("]"); + return removeExtraNulls(sb.toString()); + } + + private static String removeExtraNulls(String data) { + int i = data.length() - 1; + while (!(data.charAt(i) >= 48 && data.charAt(i) <= 57)) { + i--; + } + return data.substring(0, i + 1) + "]"; + } + + /** + * + * @param data + * @return + */ + public static TreeNode deserialize(String data) { + data = data.substring(1, data.length() - 1); + + if (data.length() == 0) { + return null; + } + + String[] values = data.split(", "); + + TreeNode root = new TreeNode(Integer.parseInt(values[0])); + + Queue queue = new LinkedList<>(); + queue.add(root); + + for (int i = 0; i < values.length && !queue.isEmpty(); i += 2) { + TreeNode currNode = queue.poll(); + + if (i + 1 < values.length && !values[i + 1].equals("null")) { + TreeNode leftNode = new TreeNode(Integer.parseInt(values[i + 1])); + currNode.left = leftNode; + queue.add(leftNode); + } + + if (i + 2 < values.length && !values[i + 2].equals("null")) { + TreeNode rightNode = new TreeNode(Integer.parseInt(values[i + 2])); + currNode.right = rightNode; + queue.add(rightNode); + } + } + + return root; + } + + public static void main(String[] args) { + // TODO Convert the print statements to asserts + + System.out.println(serialize(new TreeNode(1))); + + /* + Binary Tree + + 1 + / \ + 2 3 + / \ + 4 5 + */ + TreeNode tree = new TreeNode(1); + tree.left = new TreeNode(2); + tree.right = new TreeNode(3); + tree.left.left = new TreeNode(4); + tree.left.right = new TreeNode(5); + + System.out.println(serialize(tree)); + + System.out.println(serialize(deserialize(serialize(tree)))); + + System.out.println(serialize(deserialize(serialize(null)))); + + TreeNode tree2 = new TreeNode(1); + tree2.right = new TreeNode(2); + tree2.right.right = new TreeNode(3); + tree2.right.right.right = new TreeNode(4); + tree2.right.right.right.right = new TreeNode(5); + tree2.right.right.right.right.right = new TreeNode(6); + tree2.right.right.right.right.right.right = new TreeNode(7); + tree2.right.right.right.right.right.right.right = new TreeNode(8); + + System.out.println(serialize(tree2)); + System.out.println(serialize(deserialize(serialize(tree2)))); + + System.out.println("---"); + + System.out.println(serialize(deserialize("[1, 2]"))); + System.out.println(serialize(deserialize("[1, 2, 3]"))); + System.out.println(serialize(deserialize("[3, 2, 4, 1]"))); + System.out.println(serialize(deserialize("[3, 2, 4, 1, 5, 6]"))); + System.out.println(serialize(deserialize("[1, 2, 3, null, null, 4, 5]"))); + System.out.println(serialize(deserialize("[5, 2, 3, null, null, 2, 4, 3, 1]"))); + + System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5]"))); + System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5, null, 6]"))); + System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5, null, 6, null, 7]"))); + System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5, null, 6, null, 7, null, 8]"))); + System.out.println(serialize(deserialize("[1, null, 2, null, 3, null, 4, null, 5, null, 6, null, 7, null, 8, null, 9]"))); + } +} \ No newline at end of file From dfe3fdd68432d226b17f424dd5343e5aca85e73e Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Sun, 18 Aug 2019 00:16:35 +0100 Subject: [PATCH 06/26] Exclusive Time Functions: done --- .../stacks/ExclusiveTimeOfFunctions.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java diff --git a/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java b/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java new file mode 100644 index 00000000..169f41a2 --- /dev/null +++ b/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java @@ -0,0 +1,89 @@ +package com.leetcode.stacks; + +import javafx.util.Pair; + +import java.util.Arrays; +import java.util.List; +import java.util.Stack; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Medium + * Link: https://leetcode.com/problems/exclusive-time-of-functions/ + * Description: + * On a single threaded CPU, we execute some functions. Each function has a unique id between 0 and N-1. + * + * We store logs in timestamp order that describe when a function is entered or exited. + * + * Each log is a string with this format: "{function_id}:{"start" | "end"}:{timestamp}". For example, "0:start:3" + * means the function with id 0 started at the beginning of timestamp 3. "1:end:2" means the function with id 1 ended + * at the end of timestamp 2. + * + * A function's exclusive time is the number of units of time spent in this function. Note that this does not include + * any recursive calls to child functions. + * + * The CPU is single threaded which means that only one function is being executed at a given time unit. + * + * Return the exclusive time of each function, sorted by their function id. + * + * Input: + * n = 2 + * logs = ["0:start:0","1:start:2","1:end:5","0:end:6"] + * Output: [3, 4] + * Explanation: + * Function 0 starts at the beginning of time 0, then it executes 2 units of time and reaches the end of time 1. + * Now function 1 starts at the beginning of time 2, executes 4 units of time and ends at time 5. + * Function 0 is running again at the beginning of time 6, and also ends at the end of time 6, thus executing for 1 unit of time. + * So function 0 spends 2 + 1 = 3 units of total time executing, and function 1 spends 4 units of total time executing. + * + * + * Note: + * -> 1 <= n <= 100 + * -> Two functions won't start or end at the same time. + * -> Functions will always log when they exit. + * + * @author rampatra + * @since 2019-08-17 + */ +public class ExclusiveTimeOfFunctions { + + /** + * Runtime: 18 ms. + * + * @param n + * @param logs + * @return + */ + public static int[] exclusiveTime(int n, List logs) { + int[] times = new int[n]; + Stack> stack = new Stack<>(); + + for (String log : logs) { + String[] l = log.split(":"); + int id = Integer.parseInt(l[0]); + String operation = l[1]; + int timestamp = Integer.parseInt(l[2]); + + if (operation.equals("start")) { + if (!stack.empty()) { + times[stack.peek().getKey()] += (timestamp - stack.peek().getValue() - 1); + } + stack.push(new Pair<>(id, timestamp)); + } else { + times[id] += timestamp - stack.pop().getValue() + 1; + if (!stack.isEmpty()) { + stack.push(new Pair<>(stack.pop().getKey(), timestamp)); + } + } + } + + return times; + } + + public static void main(String[] args) { + assertEquals("[4]", Arrays.toString(exclusiveTime(1, Arrays.asList("0:start:0", "0:start:1", "0:end:2", "0:end:3")))); + assertEquals("[6]", Arrays.toString(exclusiveTime(1, Arrays.asList("0:start:0", "0:start:1", "0:start:2", "0:end:3", "0:end:4", "0:end:5")))); + assertEquals("[3, 4]", Arrays.toString(exclusiveTime(2, Arrays.asList("0:start:0", "1:start:2", "1:end:5", "0:end:6")))); + } +} \ No newline at end of file From 4b89f45be4290f0cb429fb011e122c8942b23e3f Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Sun, 18 Aug 2019 20:16:57 +0100 Subject: [PATCH 07/26] Max prod subarray: done --- .../MaximumProductSubArray.java | 62 +++++++++++++++++++ .../MaximumSubArray.java | 2 +- .../stacks/ExclusiveTimeOfFunctions.java | 4 +- 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/leetcode/dynamicprogramming/MaximumProductSubArray.java rename src/main/java/com/leetcode/{arrays => dynamicprogramming}/MaximumSubArray.java (98%) diff --git a/src/main/java/com/leetcode/dynamicprogramming/MaximumProductSubArray.java b/src/main/java/com/leetcode/dynamicprogramming/MaximumProductSubArray.java new file mode 100644 index 00000000..781cad13 --- /dev/null +++ b/src/main/java/com/leetcode/dynamicprogramming/MaximumProductSubArray.java @@ -0,0 +1,62 @@ +package com.leetcode.dynamicprogramming; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Medium + * Link: https://leetcode.com/problems/maximum-product-subarray/ + * Description: + * Given an integer array nums, find the contiguous subarray within an array (containing at least one number) which + * has the largest product. + *

+ * Example 1: + * Input: [2,3,-2,4] + * Output: 6 + * Explanation: [2,3] has the largest product 6. + *

+ * Example 2: + * Input: [-2,0,-1] + * Output: 0 + * Explanation: The result cannot be 2, because [-2,-1] is not a subarray. + * + * @author rampatra + * @since 2019-08-18 + */ +public class MaximumProductSubArray { + + /** + * The approach is similar to {@link MaximumSubArray} where we update maxUntilIndex only if multiplying the current + * number to the product of of all numbers until index produces a larger product and if not make maxUntilIndex the + * current number. The only twist here is that we keep two such variables, one for max and one for min, and that's + * because the product of two negatives gives us a positive number. + *

+ * Runtime: 1 ms. + * + * @param nums + * @return + */ + public static int maxProduct(int[] nums) { + int maxProd = nums[0]; + int maxUntilIndex = nums[0]; + int minUntilIndex = nums[0]; + + for (int i = 1; i < nums.length; i++) { + if (nums[i] >= 0) { + maxUntilIndex = Math.max(nums[i], maxUntilIndex * nums[i]); + minUntilIndex = Math.min(nums[i], minUntilIndex * nums[i]); + } else { + int prevMaxUntilIndex = maxUntilIndex; + maxUntilIndex = Math.max(nums[i], minUntilIndex * nums[i]); // when current number is -ve then multiply with minUntilIndex to get the max as product of two negatives is a positive + minUntilIndex = Math.min(nums[i], prevMaxUntilIndex * nums[i]); + } + + maxProd = Math.max(maxProd, maxUntilIndex); + } + + return maxProd; + } + + public static void main(String[] args) { + assertEquals(24, maxProduct(new int[]{-2, 3, -4})); + } +} \ No newline at end of file diff --git a/src/main/java/com/leetcode/arrays/MaximumSubArray.java b/src/main/java/com/leetcode/dynamicprogramming/MaximumSubArray.java similarity index 98% rename from src/main/java/com/leetcode/arrays/MaximumSubArray.java rename to src/main/java/com/leetcode/dynamicprogramming/MaximumSubArray.java index f9a64a3f..90a28c93 100644 --- a/src/main/java/com/leetcode/arrays/MaximumSubArray.java +++ b/src/main/java/com/leetcode/dynamicprogramming/MaximumSubArray.java @@ -1,4 +1,4 @@ -package com.leetcode.arrays; +package com.leetcode.dynamicprogramming; /** * Level: Easy diff --git a/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java b/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java index 169f41a2..63c61dc2 100644 --- a/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java +++ b/src/main/java/com/leetcode/stacks/ExclusiveTimeOfFunctions.java @@ -66,13 +66,13 @@ public static int[] exclusiveTime(int n, List logs) { int timestamp = Integer.parseInt(l[2]); if (operation.equals("start")) { - if (!stack.empty()) { + if (!stack.empty()) { // if there are other processes started before, calculate their time until now times[stack.peek().getKey()] += (timestamp - stack.peek().getValue() - 1); } stack.push(new Pair<>(id, timestamp)); } else { times[id] += timestamp - stack.pop().getValue() + 1; - if (!stack.isEmpty()) { + if (!stack.isEmpty()) { // if there are other processes, make their start time to now stack.push(new Pair<>(stack.pop().getKey(), timestamp)); } } From b2aba3e6fcf22bf24ce6b8c3089a372bf7852063 Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Sun, 18 Aug 2019 22:37:11 +0100 Subject: [PATCH 08/26] linked list cycle done --- .../linkedlists/LinkedListCycleII.java | 73 +++++++++++++++++++ .../linkedlists/DetectAndRemoveLoop.java | 25 ++++++- 2 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/leetcode/linkedlists/LinkedListCycleII.java diff --git a/src/main/java/com/leetcode/linkedlists/LinkedListCycleII.java b/src/main/java/com/leetcode/linkedlists/LinkedListCycleII.java new file mode 100644 index 00000000..d5fe0e50 --- /dev/null +++ b/src/main/java/com/leetcode/linkedlists/LinkedListCycleII.java @@ -0,0 +1,73 @@ +package com.leetcode.linkedlists; + +/** + * Level: Medium + * Link: https://leetcode.com/problems/linked-list-cycle-ii/ + * Description: + * Given a linked list, return the node where the cycle begins. If there is no cycle, return null. + * + * To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in + * the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list. + * + * Note: Do not modify the linked list. + * + * Example 1: + * + * Input: head = [3,2,0,-4], pos = 1 + * Output: tail connects to node index 1 + * Explanation: There is a cycle in the linked list, where tail connects to the second node. + * + * + * Example 2: + * + * Input: head = [1,2], pos = 0 + * Output: tail connects to node index 0 + * Explanation: There is a cycle in the linked list, where tail connects to the first node. + * + * + * Example 3: + * + * Input: head = [1], pos = -1 + * Output: no cycle + * Explanation: There is no cycle in the linked list. + * + * Follow-up: + * Can you solve it without using extra space? + * + * @author rampatra + * @since 2019-08-18 + */ +public class LinkedListCycleII { + + /** + * Runtime: 0 ms. + * + * @param head + * @return + */ + public Node detectCycle(Node head) { + Node slow = head; + Node fast = head; + + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + if (slow == fast) { + break; + } + } + + if (fast == null || fast.next == null) { + return null; + } else { + slow = head; + + while (slow != fast) { + slow = slow.next; + fast = fast.next; + } + + return slow; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/rampatra/linkedlists/DetectAndRemoveLoop.java b/src/main/java/com/rampatra/linkedlists/DetectAndRemoveLoop.java index ade19e90..5ad549d4 100644 --- a/src/main/java/com/rampatra/linkedlists/DetectAndRemoveLoop.java +++ b/src/main/java/com/rampatra/linkedlists/DetectAndRemoveLoop.java @@ -34,6 +34,11 @@ public class DetectAndRemoveLoop { * ii. Now, move both slow and fast pointer at same pace and where they meet is the starting point of the loop. * iii. Lastly, to remove the loop make the next of the node (before the starting point of loop) to null. * + * Proof for Floyd's Cycle Detection: Consider a cyclic list and imagine the slow and fast pointers are two runners + * racing around a circle track. The fast runner will eventually meet the slow runner. Why? Consider this case - + * The fast runner is just one step behind the slow runner. In the next iteration, they both increment one and two + * steps respectively and meet each other. + * * @param list * @param * @return {@code true} if loop exists {@code false} otherwise. @@ -58,7 +63,7 @@ public static > boolean detectAndRemoveLoop(SingleLinked while (true) { slow = slow.next; fast = fast.next; - if (slow.next == fast.next) { + if (slow == fast) { fast.next = null; break; } @@ -78,5 +83,23 @@ public static void main(String[] args) { linkedList.getNode(4).next = linkedList.getNode(2); System.out.println(detectAndRemoveLoop(linkedList)); linkedList.printList(); + + linkedList = new SingleLinkedList<>(); + linkedList.add(0); + linkedList.add(1); + linkedList.getNode(1).next = linkedList.getNode(0); + System.out.println(detectAndRemoveLoop(linkedList)); + linkedList.printList(); + + linkedList = new SingleLinkedList<>(); + linkedList.add(0); + System.out.println(detectAndRemoveLoop(linkedList)); + linkedList.printList(); + + linkedList = new SingleLinkedList<>(); + linkedList.add(0); + linkedList.getNode(0).next = linkedList.getNode(0); + System.out.println(detectAndRemoveLoop(linkedList)); + linkedList.printList(); } } \ No newline at end of file From d97139367d39f148b629dd818f3892739dc2ea76 Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Mon, 19 Aug 2019 17:44:04 +0100 Subject: [PATCH 09/26] topk frequent elements --- .../heaps/KthLargestElementInArray.java | 143 ++++++++++++++++++ .../leetcode/heaps/TopKFrequentElements.java | 68 +++++++++ 2 files changed, 211 insertions(+) create mode 100644 src/main/java/com/leetcode/heaps/KthLargestElementInArray.java create mode 100644 src/main/java/com/leetcode/heaps/TopKFrequentElements.java diff --git a/src/main/java/com/leetcode/heaps/KthLargestElementInArray.java b/src/main/java/com/leetcode/heaps/KthLargestElementInArray.java new file mode 100644 index 00000000..2422de08 --- /dev/null +++ b/src/main/java/com/leetcode/heaps/KthLargestElementInArray.java @@ -0,0 +1,143 @@ +package com.leetcode.heaps; + +import com.rampatra.base.MaxHeap; + +import java.util.PriorityQueue; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Medium + * Link: https://leetcode.com/problems/kth-largest-element-in-an-array/ + * Description: + * Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not + * the kth distinct element. + *

+ * Example 1: + * Input: [3,2,1,5,6,4] and k = 2 + * Output: 5 + *

+ * Example 2: + * Input: [3,2,3,1,2,4,5,5,6] and k = 4 + * Output: 4 + *

+ * Note: + * You may assume k is always valid, 1 ≤ k ≤ array's length. + * + * @author rampatra + * @since 2019-08-19 + */ +public class KthLargestElementInArray { + + /** + * Runtime: 1 ms. + * + * @param nums + * @param k + * @return + */ + public static int findKthLargest(int[] nums, int k) { + return heapSortUntilK(nums, k); + } + + /** + * In heapsort, after each iteration we have the max element at the end of the array. Ergo, if we run the algorithm + * k times then we would have our kth largest element. + * + * @param a + * @param k + * @return + */ + public static int heapSortUntilK(int[] a, int k) { + buildMaxHeap(a); + int count = 0; + + for (int i = a.length - 1; i > 0; i--) { + if (count++ == k) { + break; + } + swap(a, 0, i); + maxHeapify(a, 0, i); + } + + return a[a.length - k]; + } + + /** + * Makes the array {@param a} satisfy the max heap property starting from + * {@param index} till {@param end} position in array. + *

+ * See this {@link MaxHeap#maxHeapify} for a basic version of maxHeapify. + *

+ * Time complexity: O(log n). + * + * @param a + * @param index + * @param end + */ + public static void maxHeapify(int[] a, int index, int end) { + int largest = index; + int leftIndex = 2 * index + 1; + int rightIndex = 2 * index + 2; + + if (leftIndex < end && a[index] < a[leftIndex]) { + largest = leftIndex; + } + if (rightIndex < end && a[largest] < a[rightIndex]) { + largest = rightIndex; + } + + if (largest != index) { + swap(a, index, largest); + maxHeapify(a, largest, end); + } + } + + /** + * Converts array {@param a} in to a max heap. + *

+ * Time complexity: O(n) and is not O(n log n). + */ + private static void buildMaxHeap(int[] a) { + for (int i = a.length / 2 - 1; i >= 0; i--) { + maxHeapify(a, i, a.length); + } + } + + + /** + * When you poll() on a PriorityQueue the smallest number in the queue is removed. Based on this property, we can + * iterate over the entire array and in the end we would be left with the k largest element in the queue. + * + * @param nums + * @param k + * @return + */ + public static int findKthLargestUsingPriorityQueue(int[] nums, int k) { + PriorityQueue priorityQueue = new PriorityQueue<>(); + + for (int num : nums) { + priorityQueue.add(num); + + if (priorityQueue.size() > k) { + priorityQueue.poll(); + } + } + + return priorityQueue.isEmpty() ? -1 : priorityQueue.peek(); + } + + private static void swap(int[] a, int firstIndex, int secondIndex) { + a[firstIndex] = a[firstIndex] + a[secondIndex]; + a[secondIndex] = a[firstIndex] - a[secondIndex]; + a[firstIndex] = a[firstIndex] - a[secondIndex]; + } + + public static void main(String[] args) { + assertEquals(5, findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 2)); + assertEquals(3, findKthLargest(new int[]{3, 2, 1, 5, 6, 4}, 4)); + + assertEquals(5, findKthLargestUsingPriorityQueue(new int[]{3, 2, 1, 5, 6, 4}, 2)); + assertEquals(3, findKthLargestUsingPriorityQueue(new int[]{3, 2, 1, 5, 6, 4}, 4)); + } +} diff --git a/src/main/java/com/leetcode/heaps/TopKFrequentElements.java b/src/main/java/com/leetcode/heaps/TopKFrequentElements.java new file mode 100644 index 00000000..5a684325 --- /dev/null +++ b/src/main/java/com/leetcode/heaps/TopKFrequentElements.java @@ -0,0 +1,68 @@ +package com.leetcode.heaps; + +import javafx.util.Pair; + +import java.util.*; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Medium + * Link: https://leetcode.com/problems/top-k-frequent-elements/ + * Description: + * Given a non-empty array of integers, return the k most frequent elements. + *

+ * Example 1: + * Input: nums = [1,1,1,2,2,3], k = 2 + * Output: [1,2] + *

+ * Example 2: + * Input: nums = [1], k = 1 + * Output: [1] + *

+ * Note: + * - You may assume k is always valid, 1 ≤ k ≤ number of unique elements. + * - Your algorithm's time complexity must be better than O(n log n), where n is the array's size. + * + * @author rampatra + * @since 2019-08-19 + */ +public class TopKFrequentElements { + + /** + * TODO: A faster approach without using Pair. + *

+ * Runtime: 51 ms. + * + * @param nums + * @param k + * @return + */ + public static List topKFrequent(int[] nums, int k) { + Map numCount = new HashMap<>(); + PriorityQueue> pq = new PriorityQueue<>(Comparator.comparing(Pair::getValue)); + + for (int num : nums) { + numCount.put(num, numCount.getOrDefault(num, 0) + 1); + } + + for (Map.Entry entry : numCount.entrySet()) { + pq.add(new Pair<>(entry.getKey(), entry.getValue())); + + if (pq.size() > k) { + pq.poll(); + } + } + + return pq.stream().map(Pair::getKey).collect(Collectors.toList()); + } + + public static void main(String[] args) { + assertEquals("[2, 1]", topKFrequent(new int[]{1, 1, 1, 2, 2, 3}, 2).toString()); + assertEquals("[0]", topKFrequent(new int[]{3, 0, 1, 0}, 1).toString()); + assertEquals("[1]", topKFrequent(new int[]{1}, 1).toString()); + assertEquals("[1, 2]", topKFrequent(new int[]{1, 2}, 2).toString()); + assertEquals("[2, -1]", topKFrequent(new int[]{4, 1, -1, 2, -1, 2, 3}, 2).toString()); + } +} From 788eb3dec3a1cdb96f25eecf650ccad766079d2c Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Mon, 19 Aug 2019 20:39:53 +0100 Subject: [PATCH 10/26] binary search questions: done --- .../binarysearch/SearchInsertPosition.java | 63 ++++++++++++++ .../SmallestLetterGreaterThanTarget.java | 87 +++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java create mode 100644 src/main/java/com/leetcode/arrays/binarysearch/SmallestLetterGreaterThanTarget.java diff --git a/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java b/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java new file mode 100644 index 00000000..ead76d2a --- /dev/null +++ b/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java @@ -0,0 +1,63 @@ +package com.leetcode.arrays.binarysearch; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Easy + * Link: https://leetcode.com/problems/search-insert-position/ + * Description: + * Given a sorted array and a target value, return the index if the target is found. If not, return the index where it + * would be if it were inserted in order. + *

+ * You may assume no duplicates in the array. + *

+ * Example 1: + * Input: [1,3,5,6], 5 + * Output: 2 + *

+ * Example 2: + * Input: [1,3,5,6], 2 + * Output: 1 + *

+ * Example 3: + * Input: [1,3,5,6], 7 + * Output: 4 + *

+ * Example 4: + * Input: [1,3,5,6], 0 + * Output: 0 + * + * Similar question: {@link SmallestLetterGreaterThanTarget}. + * + * @author rampatra + * @since 2019-08-19 + */ +public class SearchInsertPosition { + + /** + * Runtime: 0 ms. + * + * @param nums + * @param target + * @return + */ + public static int searchInsert(int[] nums, int target) { + int low = 0; + int high = nums.length - 1; + while (low <= high) { + int mid = low + (high - low) / 2; + if (nums[mid] == target) { + return mid; + } else if (nums[mid] < target) { + low = mid + 1; + } else { + high = mid - 1; + } + } + return low; + } + + public static void main(String[] args) { + assertEquals(2, searchInsert(new int[]{1, 2}, 3)); + } +} \ No newline at end of file diff --git a/src/main/java/com/leetcode/arrays/binarysearch/SmallestLetterGreaterThanTarget.java b/src/main/java/com/leetcode/arrays/binarysearch/SmallestLetterGreaterThanTarget.java new file mode 100644 index 00000000..e44dc339 --- /dev/null +++ b/src/main/java/com/leetcode/arrays/binarysearch/SmallestLetterGreaterThanTarget.java @@ -0,0 +1,87 @@ +package com.leetcode.arrays.binarysearch; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Easy + * Link: https://leetcode.com/problems/find-smallest-letter-greater-than-target/ + * Description: + * Given a list of sorted characters letters containing only lowercase letters, and given a target letter target, find + * the smallest element in the list that is larger than the given target. + * + * Letters also wrap around. For example, if the target is target = 'z' and letters = ['a', 'b'], the answer is 'a'. + * + * Examples: + * + * Input: + * letters = ["c", "f", "j"] + * target = "a" + * Output: "c" + * + * Input: + * letters = ["c", "f", "j"] + * target = "c" + * Output: "f" + * + * Input: + * letters = ["c", "f", "j"] + * target = "d" + * Output: "f" + * + * Input: + * letters = ["c", "f", "j"] + * target = "g" + * Output: "j" + * + * Input: + * letters = ["c", "f", "j"] + * target = "j" + * Output: "c" + * + * Input: + * letters = ["c", "f", "j"] + * target = "k" + * Output: "c" + * + * Note: + * - letters has a length in range [2, 10000]. + * - letters consists of lowercase letters, and contains at least 2 unique letters. + * - target is a lowercase letter. + * + * @author rampatra + * @since 2019-08-19 + */ +public class SmallestLetterGreaterThanTarget { + + /** + * Runtime: 0 ms. + * + * @param letters + * @param target + * @return + */ + public static char nextGreatestLetter(char[] letters, char target) { + int low = 0, hi = letters.length - 1; + while (low <= hi) { + int mid = low + (hi - low) / 2; + if (letters[mid] <= target) { + low = mid + 1; + } else { + hi = mid - 1; + } + } + return letters[low % letters.length]; + } + + public static void main(String[] args) { + assertEquals('a', nextGreatestLetter(new char[]{'a'}, 'z')); + assertEquals('b', nextGreatestLetter(new char[]{'a', 'b'}, 'a')); + assertEquals('b', nextGreatestLetter(new char[]{'a', 'b', 'c'}, 'a')); + assertEquals('a', nextGreatestLetter(new char[]{'a', 'b', 'c'}, 'z')); + assertEquals('c', nextGreatestLetter(new char[]{'c', 'f', 'j'}, 'a')); + assertEquals('f', nextGreatestLetter(new char[]{'c', 'f', 'j'}, 'c')); + assertEquals('f', nextGreatestLetter(new char[]{'c', 'f', 'j'}, 'd')); + assertEquals('b', nextGreatestLetter(new char[]{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}, 'a')); + } +} \ No newline at end of file From 04350de4f583a9d61ea953251dc99f952d12605a Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Tue, 20 Aug 2019 13:30:39 +0100 Subject: [PATCH 11/26] pow x^n : done --- .../leetcode/arrays/binarysearch/PowXN.java | 85 +++++++++++++++++++ .../leetcode/strings/AnagramsInString.java | 2 +- 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/leetcode/arrays/binarysearch/PowXN.java diff --git a/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java b/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java new file mode 100644 index 00000000..b2a305a2 --- /dev/null +++ b/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java @@ -0,0 +1,85 @@ +package com.leetcode.arrays.binarysearch; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Medium + * Link: https://leetcode.com/problems/powx-n/ + * Description: + * Implement pow(x, n), which calculates x raised to the power n (x^n). + *

+ * Example 1: + * Input: 2.00000, 10 + * Output: 1024.00000 + *

+ * Example 2: + * Input: 2.10000, 3 + * Output: 9.26100 + *

+ * Example 3: + * Input: 2.00000, -2 + * Output: 0.25000 + * Explanation: 2^-2 = 1/22 = 1/4 = 0.25 + *

+ * Note: + * -100.0 < x < 100.0 + * n is a 32-bit signed integer, within the range [−231, 231 − 1] + * + * @author rampatra + * @since 2019-08-19 + */ +public class PowXN { + + /** + * In this approach we iterate n times and keep multiplying x with x. + * Runtime: Time limit exceeded. + * + * @param x + * @param n + * @return + */ + public static double myPowNaive(double x, int n) { + if (n == 0) { + return 1; + } + double res = x; + int absN = Math.abs(n); + for (int i = 1; i < absN; i++) { + res *= x; + } + return n < 0 ? 1 / res : res; + } + + + /** + * In this approach, we iterate log n times. We omit half of n each time. When n is odd, we store whatever product + * we have calculated so far in the final result. + *

+ * Runtime: 1 ms. + * + * @param x + * @param n + * @return + */ + public static double myPow(double x, int n) { + double res = 1; + long absN = Math.abs((long) n); + + while (absN > 0) { + if (absN % 2 == 1) res *= x; // store whatever we have calculated so far in the final result + x *= x; + absN /= 2; + } + return n < 0 ? 1 / res : res; + } + + public static void main(String[] args) { + assertEquals(1024.0, myPowNaive(2.0, 10)); + assertEquals(0.25, myPowNaive(2.0, -2)); + assertEquals(0.0, myPowNaive(0.00001, 2147483647)); + + assertEquals(1024.0, myPow(2.0, 10)); + assertEquals(0.25, myPow(2.0, -2)); + assertEquals(0.0, myPow(0.00001, 2147483647)); + } +} diff --git a/src/main/java/com/leetcode/strings/AnagramsInString.java b/src/main/java/com/leetcode/strings/AnagramsInString.java index afdb3f9f..444fcca4 100644 --- a/src/main/java/com/leetcode/strings/AnagramsInString.java +++ b/src/main/java/com/leetcode/strings/AnagramsInString.java @@ -55,7 +55,7 @@ private static List findAllAnagramsInTextNaive(String text, String patt * where, * n = length of text or number of characters in text *

- * Runtime: 7 ms on leetcode. + * Runtime: 6 ms. * * @param text * @param pattern From a718d3dec8eefec356c3912f210959456cf3e12c Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Tue, 20 Aug 2019 14:08:56 +0100 Subject: [PATCH 12/26] sqrt x: done --- .../leetcode/arrays/binarysearch/PowXN.java | 2 +- .../binarysearch/SearchInsertPosition.java | 3 +- .../leetcode/arrays/binarysearch/SqrtX.java | 62 +++++++++++++++++++ .../leetcode/strings/AnagramsInString.java | 34 +++++++++- 4 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/leetcode/arrays/binarysearch/SqrtX.java diff --git a/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java b/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java index b2a305a2..3591c50e 100644 --- a/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java +++ b/src/main/java/com/leetcode/arrays/binarysearch/PowXN.java @@ -63,7 +63,7 @@ public static double myPowNaive(double x, int n) { */ public static double myPow(double x, int n) { double res = 1; - long absN = Math.abs((long) n); + long absN = Math.abs((long) n); // used a long so that `absN / 2` doesn't overflow while (absN > 0) { if (absN % 2 == 1) res *= x; // store whatever we have calculated so far in the final result diff --git a/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java b/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java index ead76d2a..2f13214a 100644 --- a/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java +++ b/src/main/java/com/leetcode/arrays/binarysearch/SearchInsertPosition.java @@ -26,7 +26,7 @@ * Example 4: * Input: [1,3,5,6], 0 * Output: 0 - * + *

* Similar question: {@link SmallestLetterGreaterThanTarget}. * * @author rampatra @@ -59,5 +59,6 @@ public static int searchInsert(int[] nums, int target) { public static void main(String[] args) { assertEquals(2, searchInsert(new int[]{1, 2}, 3)); + assertEquals(1, searchInsert(new int[]{1, 3, 5, 6}, 2)); } } \ No newline at end of file diff --git a/src/main/java/com/leetcode/arrays/binarysearch/SqrtX.java b/src/main/java/com/leetcode/arrays/binarysearch/SqrtX.java new file mode 100644 index 00000000..0dde1308 --- /dev/null +++ b/src/main/java/com/leetcode/arrays/binarysearch/SqrtX.java @@ -0,0 +1,62 @@ +package com.leetcode.arrays.binarysearch; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Easy + * Link: https://leetcode.com/problems/sqrtx/ + * Description: + * Implement int sqrt(int x). + * + * Compute and return the square root of x, where x is guaranteed to be a non-negative integer. + * + * Since the return type is an integer, the decimal digits are truncated and only the integer part + * of the result is returned. + * + * Example 1: + * Input: 4 + * Output: 2 + * + * Example 2: + * Input: 8 + * Output: 2 + * Explanation: The square root of 8 is 2.82842..., and since + * the decimal part is truncated, 2 is returned. + * + * @author rampatra + * @since 2019-08-19 + */ +public class SqrtX { + + /** + * Runtime: 1 ms. + * + * @param x + * @return + */ + public static int mySqrt(int x) { + if (x == 0 || x == 1) { + return x; + } + long low = 1; + long high = x / 2; + + while (low <= high) { + long mid = low + (high - low) / 2; + if (mid * mid == x) { + return (int) mid; + } else if (mid * mid < x) { + low = mid + 1; + } else { + high = mid - 1; + } + } + return (int) high; + } + + public static void main(String[] args) { + assertEquals(2, mySqrt(8)); + assertEquals(3, mySqrt(9)); + assertEquals(46339, mySqrt(2147395599)); + } +} \ No newline at end of file diff --git a/src/main/java/com/leetcode/strings/AnagramsInString.java b/src/main/java/com/leetcode/strings/AnagramsInString.java index 444fcca4..12e7d766 100644 --- a/src/main/java/com/leetcode/strings/AnagramsInString.java +++ b/src/main/java/com/leetcode/strings/AnagramsInString.java @@ -5,8 +5,40 @@ import java.util.List; /** - * Level: Easy + * Level: Medium * Problem: https://leetcode.com/problems/find-all-anagrams-in-a-string/ + * Description: + * Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. + * + * Strings consists of lowercase English letters only and the length of both strings s and p will not be larger + * than 20,100. + * + * The order of output does not matter. + * + * Example 1: + * + * Input: + * s: "cbaebabacd" p: "abc" + * + * Output: + * [0, 6] + * + * Explanation: + * The substring with start index = 0 is "cba", which is an anagram of "abc". + * The substring with start index = 6 is "bac", which is an anagram of "abc". + * + * Example 2: + * + * Input: + * s: "abab" p: "ab" + * + * Output: + * [0, 1, 2] + * + * Explanation: + * The substring with start index = 0 is "ab", which is an anagram of "ab". + * The substring with start index = 1 is "ba", which is an anagram of "ab". + * The substring with start index = 2 is "ab", which is an anagram of "ab". * * @author rampatra * @since 2019-04-13 From 9a10dadd404b2d0b441e43304223fa0bca5eb8d6 Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Tue, 20 Aug 2019 21:10:06 +0100 Subject: [PATCH 13/26] lfu cache: 90% done --- .../java/com/leetcode/design/LFUCache.java | 127 ++++++++++++++++++ .../com/rampatra/linkedlists/LRUCache.java | 16 ++- 2 files changed, 136 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/leetcode/design/LFUCache.java diff --git a/src/main/java/com/leetcode/design/LFUCache.java b/src/main/java/com/leetcode/design/LFUCache.java new file mode 100644 index 00000000..0a3e9b8e --- /dev/null +++ b/src/main/java/com/leetcode/design/LFUCache.java @@ -0,0 +1,127 @@ +package com.leetcode.design; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Hard + * Link: https://leetcode.com/problems/lfu-cache/ + * Description: + * Design and implement a data structure for Least Frequently Used (LFU) cache. It should support the following + * operations: get and put. + * + * get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. + * put(key, value) - Set or insert the value if the key is not already present. When the cache reaches its capacity, it + * should invalidate the least frequently used item before inserting a new item. For the purpose of this problem, when + * there is a tie (i.e., two or more keys that have the same frequency), the least recently used key would be evicted. + * + * Follow up: + * Could you do both operations in O(1) time complexity? + * + * Note: + * - + * + * @author rampatra + * @since 2019-08-20 + */ +public class LFUCache { + + private int minCount = 0; + private int capacity; + private Map keyValueMap; + private Map keyCountMap; + private Map> countKeysMap; + + + public LFUCache(int capacity) { + this.capacity = capacity; + keyValueMap = new HashMap<>(); + keyCountMap = new HashMap<>(); + countKeysMap = new HashMap<>(); + } + + + public int get(int key) { + Integer val = keyValueMap.get(key); + if (val == null) { + return -1; + } + + int prevCount = keyCountMap.get(key); + countKeysMap.getOrDefault(prevCount, new LinkedHashSet<>()).remove(key); + countKeysMap.putIfAbsent(prevCount + 1, new LinkedHashSet<>()); + countKeysMap.get(prevCount + 1).add(key); + + if (prevCount == minCount && countKeysMap.get(prevCount).size() == 0) { + minCount++; + } + + return val; + } + + + public void put(int key, int value) { + if (capacity <= 0) { + return; + } + + if (!keyValueMap.containsKey(key) && keyCountMap.size() == capacity) { + int keyToEvict = countKeysMap.get(minCount).iterator().next(); + countKeysMap.get(minCount).remove(keyToEvict); + keyValueMap.remove(keyToEvict); + keyCountMap.remove(keyToEvict); + } + + keyValueMap.put(key, value); + int prevCount = keyCountMap.getOrDefault(key, 0); + keyCountMap.put(key, 1); + + countKeysMap.getOrDefault(prevCount, new LinkedHashSet<>()).remove(key); + countKeysMap.putIfAbsent(1, new LinkedHashSet<>()); + countKeysMap.get(1).add(key); + + minCount = 1; + } + + + public static void main(String[] args) { + LFUCache lfuCache = new LFUCache(2); + lfuCache.put(2, 2); + lfuCache.put(3, 3); + lfuCache.put(4, 4); + assertEquals(-1, lfuCache.get(2)); + assertEquals(3, lfuCache.get(3)); + lfuCache.put(5, 5); + assertEquals(-1, lfuCache.get(4)); + + lfuCache = new LFUCache(2); + lfuCache.put(3, 1); + lfuCache.put(2, 1); + lfuCache.put(2, 2); + lfuCache.put(4, 4); + assertEquals(-1, lfuCache.get(3)); + assertEquals(2, lfuCache.get(2)); + + lfuCache = new LFUCache(2); + lfuCache.put(2, 1); + lfuCache.put(2, 2); + assertEquals(2, lfuCache.get(2)); + lfuCache.put(1, 1); + lfuCache.put(4, 4); + assertEquals(2, lfuCache.get(2)); + + lfuCache = new LFUCache(2); + assertEquals(-1, lfuCache.get(2)); + lfuCache.put(2, 6); + assertEquals(-1, lfuCache.get(1)); + lfuCache.put(1, 1); + lfuCache.put(1, 2); + assertEquals(2, lfuCache.get(1)); + assertEquals(6, lfuCache.get(2)); + + // todo fix some test cases https://leetcode.com/submissions/detail/253376947/ + } +} \ No newline at end of file diff --git a/src/main/java/com/rampatra/linkedlists/LRUCache.java b/src/main/java/com/rampatra/linkedlists/LRUCache.java index 5a8d12f1..ed046035 100644 --- a/src/main/java/com/rampatra/linkedlists/LRUCache.java +++ b/src/main/java/com/rampatra/linkedlists/LRUCache.java @@ -2,6 +2,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; +import java.util.LinkedHashSet; import java.util.Map; /** @@ -20,7 +21,7 @@ */ public class LRUCache { - LinkedHashMap linkedHashMap; + private LinkedHashMap linkedHashMap; // initialize cache LRUCache(final int size) { @@ -37,7 +38,7 @@ V add(E key, V value) { } V get(E key) { - return linkedHashMap.get(key); + return linkedHashMap.get(key); } private void print() { @@ -52,12 +53,13 @@ public static void main(String[] args) { cache.add(1, 1); cache.add(2, 2); cache.add(3, 3); + cache.print(); // initial cache contents + + cache.add(4, 4); // should remove 1 as it was accessed last cache.print(); - if (cache.get(4) == null) { - cache.add(4, 4); - } - cache.print(); - cache.add(5, 5); + + cache.get(2); + cache.add(5, 5); // should remove 3 as 2 was recently accessed cache.print(); } } From 27a92f7a20c771a41facd1aedc5f96061d16cb7a Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Tue, 20 Aug 2019 21:38:36 +0100 Subject: [PATCH 14/26] lru cache: done --- .../java/com/leetcode/design/LFUCache.java | 2 +- .../java/com/leetcode/design/LRUCache.java | 61 +++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/leetcode/design/LRUCache.java diff --git a/src/main/java/com/leetcode/design/LFUCache.java b/src/main/java/com/leetcode/design/LFUCache.java index 0a3e9b8e..595b5a52 100644 --- a/src/main/java/com/leetcode/design/LFUCache.java +++ b/src/main/java/com/leetcode/design/LFUCache.java @@ -22,7 +22,7 @@ * Could you do both operations in O(1) time complexity? * * Note: - * - + * - When setting a key which is already present, reset its frequency/count to 1. * * @author rampatra * @since 2019-08-20 diff --git a/src/main/java/com/leetcode/design/LRUCache.java b/src/main/java/com/leetcode/design/LRUCache.java new file mode 100644 index 00000000..162889f2 --- /dev/null +++ b/src/main/java/com/leetcode/design/LRUCache.java @@ -0,0 +1,61 @@ +package com.leetcode.design; + +import java.util.LinkedHashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Level: Medium + * Link: https://leetcode.com/problems/lru-cache/ + * Description: + * Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following + * operations: get and put. + * + * get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. + * put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it + * should invalidate the least recently used item before inserting a new item. + * + * The cache is initialized with a positive capacity. + * + * Follow up: + * Could you do both operations in O(1) time complexity? + * + * Runtime: 54 ms. + * + * @author rampatra + * @since 2019-08-20 + */ +public class LRUCache { + + private LinkedHashMap cache; + + public LRUCache(int capacity) { + this.cache = new LinkedHashMap(capacity, 0.75f, true) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > capacity; + } + }; + } + + public int get(int key) { + Integer val = cache.get(key); + return val == null ? -1 : val; + } + + public void put(int key, int value) { + cache.put(key, value); + } + + public static void main(String[] args) { + LRUCache cache = new LRUCache(2); + cache.put(1,1); + cache.put(2,2); + cache.put(1,1); + cache.put(3,3); + assertEquals(1, cache.get(1)); + assertEquals(-1, cache.get(2)); + assertEquals(3, cache.get(3)); + } +} \ No newline at end of file From 142a8495ff206f860a0c1ab9a91773a4d8fac439 Mon Sep 17 00:00:00 2001 From: Ram Patra Date: Wed, 21 Aug 2019 13:59:15 +0100 Subject: [PATCH 15/26] minor refactorings --- .../treesandgraphs/FirstCommonAncestor.java | 5 +++- .../com/leetcode/arrays/BuySellStocks.java | 22 +++++++++++++++++- .../com/leetcode/arrays/BuySellStocksII.java | 4 ++-- .../com/leetcode/arrays/MergeSortedArray.java | 15 +++++++++++- .../java/com/leetcode/arrays/RotateArray.java | 23 ++++++++++++++++++- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestor.java b/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestor.java index f1fc5293..38977be3 100644 --- a/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestor.java +++ b/src/main/java/com/ctci/treesandgraphs/FirstCommonAncestor.java @@ -5,6 +5,9 @@ * tree. Avoid storing additional nodes in a data structure. Also, for this question, the tree node * does NOT have access to its parent node. NOTE: This is not necessarily a binary search tree. * + * First Common Ancestor or the Least/Lowest Common Ancestor of two nodes is a node which is the + * closest to both of the nodes. + * * @author rampatra * @since 2019-02-24 */ @@ -18,7 +21,7 @@ public class FirstCommonAncestor { * - Returns null, if neither p nor q are in root's subtree. * - Else, returns the common ancestor of p and q. *

- * See {@link com.rampatra.trees.LeastCommonAncestorInBT} for a simpler version. + * See {@link com.rampatra.trees.LeastCommonAncestorInBT} for a better answer. * * @param root * @param a diff --git a/src/main/java/com/leetcode/arrays/BuySellStocks.java b/src/main/java/com/leetcode/arrays/BuySellStocks.java index d94c3296..4d4ba02b 100644 --- a/src/main/java/com/leetcode/arrays/BuySellStocks.java +++ b/src/main/java/com/leetcode/arrays/BuySellStocks.java @@ -2,7 +2,27 @@ /** * Level: Easy - * Problem: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ + * Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock/ + * Description: + * Say you have an array for which the ith element is the price of a given stock on day i. + * + * 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. + * + * Note that you cannot sell a stock before you buy one. + * + * Example 1: + * + * Input: [7,1,5,3,6,4] + * Output: 5 + * Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5. + * Not 7-1 = 6, as selling price needs to be larger than buying price. + * + * Example 2: + * + * Input: [7,6,4,3,1] + * Output: 0 + * Explanation: In this case, no transaction is done, i.e. max profit = 0. * * @author rampatra * @since 2019-04-23 diff --git a/src/main/java/com/leetcode/arrays/BuySellStocksII.java b/src/main/java/com/leetcode/arrays/BuySellStocksII.java index 47966b48..d215246e 100644 --- a/src/main/java/com/leetcode/arrays/BuySellStocksII.java +++ b/src/main/java/com/leetcode/arrays/BuySellStocksII.java @@ -2,8 +2,8 @@ /** * Level: Easy - * Problem Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ - * Problem Description: + * Link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/ + * Description: * Say you have an array for which the ith element is the price of a given stock on day i. *

* Design an algorithm to find the maximum profit. You may complete as many transactions as you diff --git a/src/main/java/com/leetcode/arrays/MergeSortedArray.java b/src/main/java/com/leetcode/arrays/MergeSortedArray.java index 09cd730d..975db8ec 100644 --- a/src/main/java/com/leetcode/arrays/MergeSortedArray.java +++ b/src/main/java/com/leetcode/arrays/MergeSortedArray.java @@ -4,7 +4,20 @@ /** * Level: Easy - * Problem Link: https://leetcode.com/problems/merge-sorted-array/ + * Link: https://leetcode.com/problems/merge-sorted-array/ + * Description: + * Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. + * + * Note: + * The number of elements initialized in nums1 and nums2 are m and n respectively. + * You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold + * additional elements from nums2. + * + * Example: + * Input: + * nums1 = [1,2,3,0,0,0], m = 3 + * nums2 = [2,5,6], n = 3 + * Output: [1,2,2,3,5,6] * * @author rampatra * @since 2019-04-26 diff --git a/src/main/java/com/leetcode/arrays/RotateArray.java b/src/main/java/com/leetcode/arrays/RotateArray.java index e4f6de33..91475160 100644 --- a/src/main/java/com/leetcode/arrays/RotateArray.java +++ b/src/main/java/com/leetcode/arrays/RotateArray.java @@ -4,7 +4,28 @@ /** * Level: Easy - * Problem: https://leetcode.com/problems/rotate-array/ + * Link: https://leetcode.com/problems/rotate-array/ + * Description: + * Given an array, rotate the array to the right by k steps, where k is non-negative. + * + * Example 1: + * Input: [1,2,3,4,5,6,7] and k = 3 + * Output: [5,6,7,1,2,3,4] + * Explanation: + * rotate 1 steps to the right: [7,1,2,3,4,5,6] + * rotate 2 steps to the right: [6,7,1,2,3,4,5] + * rotate 3 steps to the right: [5,6,7,1,2,3,4] + * + * Example 2: + * Input: [-1,-100,3,99] and k = 2 + * Output: [3,99,-1,-100] + * Explanation: + * rotate 1 steps to the right: [99,-1,-100,3] + * rotate 2 steps to the right: [3,99,-1,-100] + * + * Note: + * Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem. + * Could you do it in-place with O(1) extra space? * * @author rampatra * @since 2019-04-20 From 497e46319c0bbab7f106d8a03bf47f357dcfa29b Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Thu, 16 Jul 2020 09:09:21 +0100 Subject: [PATCH 16/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 989a3224..58fe8ecb 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ The repo consists of solutions to numerous problems using different data structu contains solutions to HackerRank problems which I have solved so far and questions from Cracking the Coding Interview Book _(6th Edition)_. -You can also refer to my [Java Notes](http://java.ramswaroop.me) for a quick refresh on the Java concepts. +You can also refer to my [Java Notes](http://blog.rampatra.com/category/java) for a quick refresh on the Java concepts. ## Contents From 9d705a5a9818ecb5c23b475791826896dba74d2b Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Sat, 20 Feb 2021 08:38:49 +0000 Subject: [PATCH 17/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 58fe8ecb..06b6d7b6 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ The repo consists of solutions to numerous problems using different data structu contains solutions to HackerRank problems which I have solved so far and questions from Cracking the Coding Interview Book _(6th Edition)_. -You can also refer to my [Java Notes](http://blog.rampatra.com/category/java) for a quick refresh on the Java concepts. +You can also refer to my [Java Notes](http://blog.rampatra.com/category/java) for a quick refresh on the Java concepts. Lastly, feel free to connect with me on [Twitter](https://twitter.com/ram__patra) for any queries or concerns. All the best! ## Contents From 8423f8164cd1ea0acd729d3725b7e70efc0f1e4e Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:34:56 +0100 Subject: [PATCH 18/26] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 06b6d7b6..e6ae9ca8 100644 --- a/README.md +++ b/README.md @@ -50,3 +50,5 @@ IntelliJ IDEA 2018.1.4 (Ultimate Edition) MacBook Pro 2.5 GHz Intel Core i7 16 GB 1600 MHz DDR3 + +_P.S. If my open-source project(s) benefitted you in some way or the other, a follow on [Twitter](https://twitter.com/ram__patra) would be greatly appreciated 🙇‍♂️._ From 7550901537074d35adb0eef09138383c9e162fd0 Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Mon, 28 Mar 2022 20:40:27 +0100 Subject: [PATCH 19/26] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e6ae9ca8..0bf98d9d 100644 --- a/README.md +++ b/README.md @@ -51,4 +51,6 @@ MacBook Pro 2.5 GHz Intel Core i7 16 GB 1600 MHz DDR3 +--- + _P.S. If my open-source project(s) benefitted you in some way or the other, a follow on [Twitter](https://twitter.com/ram__patra) would be greatly appreciated 🙇‍♂️._ From 82ae2fd7fc1f364a67e716d7f70ba6289f2357e6 Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Sun, 19 Jun 2022 12:42:01 +0100 Subject: [PATCH 20/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0bf98d9d..7be895d1 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ MacBook Pro --- -_P.S. If my open-source project(s) benefitted you in some way or the other, a follow on [Twitter](https://twitter.com/ram__patra) would be greatly appreciated 🙇‍♂️._ +_P.S. For any queries or concerns, [Twitter](https://twitter.com/ram__patra) is the best place to reach out to me. I'll try my best to help._ From 87c869ba97e5c18ff111ce5394323b872be5a3b9 Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Sun, 19 Jun 2022 12:49:02 +0100 Subject: [PATCH 21/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7be895d1..ce82e09f 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ MacBook Pro --- -_P.S. For any queries or concerns, [Twitter](https://twitter.com/ram__patra) is the best place to reach out to me. I'll try my best to help._ +_P.S. For any queries or concerns, you can reach out to me on [Twitter](https://twitter.com/ram__patra). I'll try my best to help 🙏._ From db15c1e0450c801aa3ee56e0d930fa3e33e3fb62 Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Sat, 6 Aug 2022 12:54:42 +0100 Subject: [PATCH 22/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ce82e09f..57f6c1b7 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ The repo consists of solutions to numerous problems using different data structu contains solutions to HackerRank problems which I have solved so far and questions from Cracking the Coding Interview Book _(6th Edition)_. -You can also refer to my [Java Notes](http://blog.rampatra.com/category/java) for a quick refresh on the Java concepts. Lastly, feel free to connect with me on [Twitter](https://twitter.com/ram__patra) for any queries or concerns. All the best! +You can also refer to my [Java Notes](http://blog.rampatra.com/category/java) for a quick refresh on the Java concepts or if you want a break from coding then can read about my [interview experiences](https://blog.rampatra.com/category/interview/) at various companies. Lastly, feel free to connect with me on [Twitter](https://twitter.com/ram__patra) for any queries or concerns. All the best! ## Contents From 957d03bfde64f6a2a0a2ba7334d6e2a3ff2a43e9 Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Wed, 12 Oct 2022 10:50:00 +0100 Subject: [PATCH 23/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57f6c1b7..b1bbc14c 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ MacBook Pro --- -_P.S. For any queries or concerns, you can reach out to me on [Twitter](https://twitter.com/ram__patra). I'll try my best to help 🙏._ +_P.S. For any queries or concerns, you can reach out to me on [Twitter](https://twitter.com/ram__patra). I'll try my best to help 🙏. And, if you're keen to know what I'm currently working on then check out [Presentify](https://presentify.compzets.com)._ From 615e19b8ee550d117308e5df0fc790731710ffa4 Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Wed, 17 Jul 2024 19:37:56 +0100 Subject: [PATCH 24/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b1bbc14c..07ebdb73 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ MacBook Pro --- -_P.S. For any queries or concerns, you can reach out to me on [Twitter](https://twitter.com/ram__patra). I'll try my best to help 🙏. And, if you're keen to know what I'm currently working on then check out [Presentify](https://presentify.compzets.com)._ +_P.S. For any queries or concerns, you can reach out to me on [Twitter](https://twitter.com/ram__patra). I'll try my best to help 🙏. And, if you're keen to know what I'm currently working on then check out [Presentify](https://presentifyapp.com), or [ToDoBar](https://todobarapp.com/)._ From 7eadd472a3578984626c4d31fec840ecead6fd28 Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Wed, 18 Dec 2024 16:12:11 +0000 Subject: [PATCH 25/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 07ebdb73..195f3c39 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ MacBook Pro --- -_P.S. For any queries or concerns, you can reach out to me on [Twitter](https://twitter.com/ram__patra). I'll try my best to help 🙏. And, if you're keen to know what I'm currently working on then check out [Presentify](https://presentifyapp.com), or [ToDoBar](https://todobarapp.com/)._ +_P.S. For any queries or concerns, you can reach out to me on [Twitter](https://twitter.com/rampatra_). I'll try my best to help 🙏. And, if you're keen to know what I'm currently working on then check out [Presentify](https://presentifyapp.com), [FaceScreen](https://facescreenapp.com/), or [ToDoBar](https://todobarapp.com/)._ From c23f98b7f70ab7ca613c34672eeaca8b38c7c43b Mon Sep 17 00:00:00 2001 From: Ram <2862724+rampatra@users.noreply.github.com> Date: Mon, 7 Apr 2025 15:38:06 +0100 Subject: [PATCH 26/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 195f3c39..33b68334 100644 --- a/README.md +++ b/README.md @@ -53,4 +53,4 @@ MacBook Pro --- -_P.S. For any queries or concerns, you can reach out to me on [Twitter](https://twitter.com/rampatra_). I'll try my best to help 🙏. And, if you're keen to know what I'm currently working on then check out [Presentify](https://presentifyapp.com), [FaceScreen](https://facescreenapp.com/), or [ToDoBar](https://todobarapp.com/)._ +_P.S. For any queries or concerns, you can reach out to me on [Twitter](https://twitter.com/rampatra_). I'll try my best to help 🙏. And, if you're keen to know what I'm currently working on then check out [Presentify](https://presentifyapp.com), [FaceScreen](https://facescreenapp.com/), [ToDoBar](https://todobarapp.com/), [SimpleFill](https://simplefillapp.com/), and [Apps.Deals](https://www.apps.deals)._