diff --git a/Week_04/id_26/Leetcode_169_26.java b/Week_04/id_26/Leetcode_169_26.java new file mode 100644 index 00000000..9368c342 --- /dev/null +++ b/Week_04/id_26/Leetcode_169_26.java @@ -0,0 +1,62 @@ +package divideandconquer; + +import java.util.HashMap; +import java.util.Map; + +// Source : https://leetcode.com/problems/majority-element/ +// Id : 169 +// Author : Fanlu Hai +// Date : 2018-05-24 +// Other : +// Tips : boyer moore voting algorithm; +// take full advantage of the situation to get the best solution. + +public class MajorityElement { + // straight forward way is to store appearance of number in a hashmap + // 16.69% 16 ms 99.07% 39.1 MB + public int majorityElementSlow(int[] nums) { +// System.out.println(nums.length / 2 + 1); + Map counter = new HashMap<>(); + + if (nums.length == 1) + return nums[0]; + + for (int num : nums) { + if (counter.containsKey(num)) { + if (counter.get(num) == nums.length / 2) + return num; + else + counter.put(num, counter.get(num) + 1); + } else + counter.put(num, 1); + } + + return -1; + } + + // boyer moore voting algorithm + // 100.00% 1ms 50.94% 41.5 MB + public int majorityElement(int[] nums) { + int count = 0; + int major = nums[0]; + + for (int num : nums) { + if (num == major) + count++; + else + count--; + if (count == -1) { + major = nums[0]; + count = 0; + } + } + return major; + } + + public static void main(String[] args) { + int[] array = {1, 2, 1}; + MajorityElement m = new MajorityElement(); + System.out.println(m.majorityElement(array)); + } + +} diff --git a/Week_04/id_26/Leetcode_211_26.java b/Week_04/id_26/Leetcode_211_26.java new file mode 100644 index 00000000..266e88dc --- /dev/null +++ b/Week_04/id_26/Leetcode_211_26.java @@ -0,0 +1,103 @@ +package com.fanlu.leetcode.trietree; + +// Source : https://leetcode.com/problems/add-and-search-word-data-structure-design/ +// Id : 211 +// Author : Fanlu Hai +// Date : 2018-05-12 +// Other : +// Tips : + +public class WordDictionary { + TrieNode root; + + /** + * Initialize your data structure here. + */ + public WordDictionary() { + root = new TrieNode(); + } + + /** + * Adds a word into the data structure. + */ + public void addWord(String word) { + TrieNode node = root; + for (char c : word.toCharArray()) { + int index = c - 'a'; + if (node.children[index] == null) { + node.children[index] = new TrieNode(); + } + node = node.children[index]; + } + node.isEndOfAWord = true; + } + + /** + * Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. + */ + // 100.00% 76.32% (54.9) + public boolean search(String word) { + return search(root, word, 0); + } + + // compare each node's children with the char at the given index of the word incrementally + public boolean search(TrieNode node, String word, int index) { + // if index is already longer than max index (length-1) + // then check if the node is the end of an work, there's no need to check its children + if (index == word.length()) { + return node.isEndOfAWord; + } + + char ch = word.charAt(index); + index++; + + if (ch == '.') { + for (TrieNode child : node.children) { + if (child != null) { + // if this child works then return true + if (search(child, word, index)) { + return true; + } + } + } + // no child's path works. + return false; + } else { + if (node.children[ch - 'a'] != null) { + return search(node.children[ch - 'a'], word, index); + } else { + return false; + } + } + } + + class TrieNode { + public TrieNode[] children = new TrieNode[26]; + public boolean isEndOfAWord = false; + + } + + public static void main(String[] args) { + WordDictionary obj = new WordDictionary(); +// obj.addWord("at"); + obj.addWord("and"); +// obj.addWord("an"); + obj.addWord("add"); +// obj.addWord("a"); + System.out.println(obj.search(".ad")); + System.out.println(obj.search("a.d")); + System.out.println(obj.search("b.")); + System.out.println(obj.search("....")); + System.out.println(obj.search("..")); + System.out.println(obj.search("a.d.")); + System.out.println(obj.search(".ad")); + } +} + + +/** + * Your WordDictionary object will be instantiated and called as such: + * WordDictionary obj = new WordDictionary(); + * obj.addWord(word); + * boolean param_2 = obj.search(word); + */ \ No newline at end of file diff --git a/Week_04/id_26/Leetcode_241_26.java b/Week_04/id_26/Leetcode_241_26.java new file mode 100644 index 00000000..adb7af5f --- /dev/null +++ b/Week_04/id_26/Leetcode_241_26.java @@ -0,0 +1,106 @@ +package divideandconquer; +// Source : https://leetcode.com/problems/different-ways-to-add-parentheses/ +// Id : 241 +// Author : Fanlu Hai +// Date : 2018-05-24 +// Other : +// Tips : "improvements" can make program run slower + +import java.util.*; + +public class DifferentWaysToAddParentheses { + + //32.84% 3 ms 34.61% 39.6 MB + public List diffWaysToComputeSlow(String input) { + List result = new LinkedList<>(); + + for (int i = 0; i < input.length(); i++) { + if (input.charAt(i) == '+' || input.charAt(i) == '-' || input.charAt(i) == '*') { + String part1 = input.substring(0, i); + String part2 = input.substring(i + 1); + + List resultPart1 = new LinkedList<>(); + List resultPart2 = new LinkedList<>(); + resultPart1 = diffWaysToComputeSlow(part1); + resultPart2 = diffWaysToComputeSlow(part2); + + // when either on is empty, nothing will be added to result + for (int res1 : resultPart1) { + for (int re2 : resultPart2) { + switch (input.charAt(i)) { + case '+': + result.add(res1 + re2); + break; + case '-': + result.add(res1 - re2); + break; + case '*': + result.add(res1 * re2); + break; + } + } + } + } + } + // if nothing is added to result list, it means the string is a number + if (result.isEmpty()) + result.add(Integer.valueOf(input)); + return result; + } + + // use map to store intermediate results to speed up recursion + Map> resultCache = new HashMap<>(); + + + //1 ms 100% 34.2 MB 100% + public List diffWaysToCompute(String input) { + + if (resultCache.containsKey(input)) + return resultCache.get(input); + + List result = new LinkedList<>(); + + for (int i = 0; i < input.length(); i++) { + if (input.charAt(i) == '+' || input.charAt(i) == '-' || input.charAt(i) == '*') { + String part1 = input.substring(0, i); + String part2 = input.substring(i + 1); + + List resultPart1 = new LinkedList<>(); + List resultPart2 = new LinkedList<>(); + resultPart1 = diffWaysToCompute(part1); + resultPart2 = diffWaysToCompute(part2); + + // when either on is empty, nothing will be added to result + for (int res1 : resultPart1) { + for (int re2 : resultPart2) { + //using swith here is not very efficient + // 78.94% 2 ms 100.00% 34.2 MB + // switch (input.charAt(i)) { +// case '+': +// result.add(res1 + re2); +// break; +// case '-': +// result.add(res1 - re2); +// break; +// case '*': +// result.add(res1 * re2); +// break; +// } + if (input.charAt(i) == '+') + result.add(res1 + re2); + else if (input.charAt(i) == '-') + result.add(res1 - re2); + else + result.add(res1 * re2); + + } + } + } + } + // if nothing is added to result list, it means the string is a number + if (result.isEmpty()) + result.add(Integer.valueOf(input)); + resultCache.put(input, result); + return result; + } +} diff --git a/Week_04/id_26/Leetcode_720_26.java b/Week_04/id_26/Leetcode_720_26.java new file mode 100644 index 00000000..45428c29 --- /dev/null +++ b/Week_04/id_26/Leetcode_720_26.java @@ -0,0 +1,158 @@ +package com.fanlu.leetcode.trietree; + +import java.util.HashMap; +import java.util.Stack; + +// Source : https://leetcode.com/problems/longest-word-in-dictionary/ +// Id : 720 +// Author : Fanlu Hai +// Date : 2018-05-12 +// Other : data structure of the children list will affect the performance significantly +// Tips : good test case ["gbra","jy","pl","zn","gb","j","jyh","jyhm","plr","znicn","p","gbr","zni","znic","aq"] +public class LongestWordInDictionary { + TrieNodeUsingMap rootNodeUsingMap = new TrieNodeUsingMap('/'); + TrieNodeUsingArray rootNodeUsingArray = new TrieNodeUsingArray('/'); + String longest = ""; + + + // 34.81%(22 ms) 97.45% + public String longestWordSlow(String[] words) { + for (int i = 0; i < words.length; i++) { + insertUsingMap(words[i], i); + // System.out.println("insertUsingMap: " + i + " " + words[i]); + } + + Stack stack = new Stack(); + stack.addAll(rootNodeUsingMap.children.values()); + + TrieNodeUsingMap node; + while (!stack.isEmpty()) { + node = stack.pop(); + // System.out.println(node.c+" "+node.index); + if (node.index != -1) { + String tmp = words[node.index]; + // System.out.println("check "+tmp); + if (tmp.length() > longest.length() + || (tmp.length() == longest.length() && tmp.compareTo(longest) < 0)) { + // System.out.println("longest "+tmp); + longest = tmp; + } + stack.addAll(node.children.values()); + } + + } + + return longest; + } + + //51.26% (16 ms) 98.36% + public String longestWordBetter(String[] words) { + for (int i = 0; i < words.length; i++) { + insertUsingMap(words[i], i); + // System.out.println("insertUsingMap: " + i + " " + words[i]); + } + for (TrieNodeUsingMap child : rootNodeUsingMap.children.values()) { + searchLongest(child, words); + } + return longest; + } + + public void searchLongest(TrieNodeUsingMap node, String[] words) { + if (node.index != -1) { + String tmp = words[node.index]; + // System.out.println("check "+tmp); + if (tmp.length() > longest.length() + || (tmp.length() == longest.length() && tmp.compareTo(longest) < 0)) { + // System.out.println("longest "+tmp); + longest = tmp; + } + for (TrieNodeUsingMap child : node.children.values()) { + searchLongest(child, words); + } + } + } + + //97.79% (6 ms) 97.18% (37.6 MB) + public String longestWord(String[] words) { + for (int i = 0; i < words.length; i++) { + insertUsingArray(words[i], i); + System.out.println("insert: " + i + " " + words[i]); + } + for (TrieNodeUsingArray child : rootNodeUsingArray.children) { + if (null != child) + searchLongest2(child, words); + } + return longest; + } + + public void searchLongest2(TrieNodeUsingArray node, String[] words) { + + if (node.index != -1) { + String tmp = words[node.index]; + // System.out.println("check "+tmp); + if (tmp.length() > longest.length() + || (tmp.length() == longest.length() && tmp.compareTo(longest) < 0)) { + System.out.println("longest " + tmp); + longest = tmp; + } + for (TrieNodeUsingArray child : node.children) { + if (null != child) + searchLongest2(child, words); + } + } + } + + class TrieNodeUsingMap { + public char c; + // to keep track which word's insertion created this node + public int index = -1; + HashMap children = new HashMap(); + + public TrieNodeUsingMap(char c) { + this.c = c; + } + + public TrieNodeUsingMap(char c, int index) { + this.c = c; + this.index = index; + } + } + + public void insertUsingMap(String string, int index) { + TrieNodeUsingMap node = rootNodeUsingMap; + for (char c : string.toCharArray()) { + node.children.putIfAbsent(c, new TrieNodeUsingMap(c)); + node = node.children.get(c); + } + // not only means this node is the end of a word,but also contains index information for this word. + node.index = index; + } + + class TrieNodeUsingArray { + public char c; + // to keep track which word's insertion created this node + public int index = -1; + TrieNodeUsingArray[] children = new TrieNodeUsingArray[26]; + + public TrieNodeUsingArray(char c) { + this.c = c; + } + + public TrieNodeUsingArray(char c, int index) { + this.c = c; + this.index = index; + } + } + + public void insertUsingArray(String string, int index) { + TrieNodeUsingArray node = rootNodeUsingArray; + for (char c : string.toCharArray()) { + int n = c - 'a'; + if (node.children[n] == null) { + node.children[n] = new TrieNodeUsingArray(c); + } + node = node.children[n]; + } + node.index = index; + } +}