diff --git a/AlienDictionary.java b/AlienDictionary.java new file mode 100644 index 0000000..c6e59d4 --- /dev/null +++ b/AlienDictionary.java @@ -0,0 +1,117 @@ + +// In this problem, we have to identify that if the claim that words are sorted in alien order is correct or not. If correct than return +// order string else return "" empty string. So here, we are first building the graph, when comparing two consecutive words at a time +// if two chars are different we get to know that first char comes before second char, so there is a relation, there is a dependency, +// therefore it is a graph problem. Keeping one map to store the dependancy(char and the list of char depending on the key char), and +// indegrees list, so we will decrement the indegree of the node by 1, if it has some dependancy. And all the independent nodes we put +// in the queue, we can start from any char that is independent(indegree as 0) so we put all in queue. Then we start the bfs, poll the +// current char, append to stringbuilder sb, and check for it's dependant nodes, reduce their indegree by 1, and if it becomes zero +// put them in the queue. + +// Time Complexity : O(nk) n length of words array and k avg length of each word +// Space Complexity : O(nk) dependancy Hashmap +// Did this code successfully run on Leetcode : yes +// Any problem you faced while coding this : no +import java.util.*; + +public class AlienDictionary { + int[] indegrees; + HashMap> m; + + public String alienOrder(String[] words) { + // Base case + if (words == null || words.length == 0) { + return ""; + } + // indegrees array of length 26, each index represent a char (a-z) + indegrees = new int[26]; + // Map for storing the char and list + m = new HashMap<>(); + // constructGraph method will fill this two data structures + constructGraph(words); + // Queue for bfs + Queue q = new java.util.LinkedList<>(); + // Ans + StringBuilder sb = new StringBuilder(); + // Iterate over the map and check if any key from map having indegree zero, put + // them in queue + for (Character key : m.keySet()) { + if (indegrees[key - 'a'] == 0) { + q.add(key); + } + } + // Start bfs + while (!q.isEmpty()) { + // poll the current + char curr = q.poll(); + // append to sb + sb.append(curr); + // Get the list of all dependant nodes(chars) + List allChar = m.get(curr); + // if it is null, continue + if (allChar.size() == 0) { + continue; + } + // Else for each char, reduce their indegree by 1 and if it becomes 0, put the + // char in queue + for (char singleChar : allChar) { + indegrees[singleChar - 'a']--; + if (indegrees[singleChar - 'a'] == 0) { + q.add(singleChar); + } + } + } + // At last if the string size is not equal to the map size, means we have not + // got the correct order + if (sb.length() != m.size()) { + return ""; + } + // Else return string + return sb.toString(); + } + + private void constructGraph(String[] words) { + // First go over each word, each char, put all the unique chars in map with + // empty list as value + for (int i = 0; i < words.length; i++) { + for (int j = 0; j < words[i].length(); j++) { + if (!m.containsKey(words[i].charAt(j))) { + m.put(words[i].charAt(j), new ArrayList<>()); + } + } + } + // Go over each words + for (int i = 0; i < words.length - 1; i++) { + // Take two consecutive words at a time + String first = words[i]; + String second = words[i + 1]; + // Take their length + int m1 = first.length(); + int n = second.length(); + // If the first word startswith second, that means not sorted, so clear map and + // return + if (first.startsWith(second) && m1 > n) { + m.clear(); + return; + } + // Else compare each char + for (int j = 0; j < n && j < m1; j++) { + char firstChar = first.charAt(j); + char secondChar = second.charAt(j); + // If different + if (firstChar != secondChar) { + // Increase the indegree of second char by 1 + indegrees[secondChar - 'a']++; + // And add to the list in map + m.get(firstChar).add(secondChar); + } + } + } + } + + public static void main(String[] args) { + String[] words = new String[] { "wrt", "wrf", "er", "ett", "rfttz" }; + AlienDictionary a = new AlienDictionary(); + System.out.println(a.alienOrder(words)); + } +} diff --git a/FindACelebrity.java b/FindACelebrity.java new file mode 100644 index 0000000..211adf5 --- /dev/null +++ b/FindACelebrity.java @@ -0,0 +1,82 @@ +// In this problem, simply traversing through the 2 by 2 matrix and maintainin a indegrees array. As we know that for a celeb since +// everyone knows celeb, the indegree value will be n-1, and since celeb doesnt know anyone the outdegree value will be 0. So in this +// indegree array if we find that i knows j, we decrement the indegree[i] by 1 indicating an outgoing edge, and increment the indegree[j] +// by 1, indicating an incoming edge. At end check if any index having n-1, that is our ans else -1. +// Time Complexity : O(n^2) +// Space Complexity : O(n) +// Did this code successfully run on Leetcode : yes +// Any problem you faced while coding this : no +public class FindACelebrity extends Relation { + public int findCeleb(int n) { + // Base case + if (n == 0) { + return -1; + } + // Indegree array + int[] indegree = new int[n]; + // Loop through n*n + for (int i = 0; i < n; i++) { + for (int j = 0; j < n; j++) { + // Check for all the combinations except i==j + if (i != j) { + // Check if the i knows j + if (knows(i, j)) { + // Decrement + indegrees[i]--; + // Increment + indegrees[j]++; + } + } + } + } + // Check what contains the n-1 value, return that i + for (int i = 0; i < n; i++) { + if (indegrees[i] == n - 1) { + return i; + } + } + // Else -1 + return -1; + } +} + +// In this approach, we are making assumption that 0 is our celeb, than running +// a loop and checking if there is anyone to whom our +// current celeb (0) knows, if yes than making that person as the celeb, becoz 0 +// is knowing someone so 0 cant be celeb. Now with this +// second celeb, we check if everyone knows him and he doenst know anyone, if +// any breach found, return -1, else return this celeb. + +// Time Complexity : O(n) +// Space Complexity : O(1) +// Did this code successfully run on Leetcode : yes +// Any problem you faced while coding this : no +public class FindACelebrity extends Relation { + public int findCeleb(int n) { + // Base case + if (n == 0) { + return -1; + } + int celeb = 0; + // Loop over and check if the first assumed celeb is knowing anyone + for (int i = 0; i < n; i++) { + if (i != celeb) { + if (knows(celeb, i)) { + // Then 0 cannot be celeb, so change the celeb to the person whom 0 knows that + // is i + celeb = i; + } + } + } + // Now again loop over and check if this celeb knows anyone or anyone doesnt + // know this celeb, then return -1, else return this celeb + for (int i = 0; i < n; i++) { + if (i != celeb) { + if (knows(i, celeb) == 0 || knows(celeb, i) == 1) { + return -1; + } + } + } + return celeb; + } +} \ No newline at end of file diff --git a/VerifyingAlienDictionary.java b/VerifyingAlienDictionary.java new file mode 100644 index 0000000..9643e0a --- /dev/null +++ b/VerifyingAlienDictionary.java @@ -0,0 +1,64 @@ +// In this problem, using hashmap to store the order string with it's index. Then going over the array and comparing each consecutive +// words, if there is any char that is not matching, checking its index value in map, if the first word char has lower index value +// than the second word char, than returning true, else false. Also if the chars match and first word has length greater than the second +// word, returning false. + +// Time Complexity : O(nk) n length of words array and k avg length of each word +// Space Complexity : O(1) +// Did this code successfully run on Leetcode : yes +// Any problem you faced while coding this : no +class Solution { + HashMap map; + + public boolean isAlienSorted(String[] words, String order) { + // Base case + if (words == null || words.length == 0) { + return true; + } + map = new HashMap<>(); + // Loop and put the order string in the map + for (int i = 0; i < order.length(); i++) { + char c = order.charAt(i); + map.put(c, i); + } + // Now loop over all words + for (int i = 0; i < words.length - 1; i++) { + // Take two consecutive words at a time + String first = words[i]; + String second = words[i + 1]; + // Check if not ordered + if (isNotOrdered(first, second)) { + // Return false + return false; + } + } + // return true + return true; + } + + private boolean isNotOrdered(String first, String second) { + // Take the length of two words + int m = first.length(); + int n = second.length(); + // Loop over each char + for (int i = 0; i < m && i < n; i++) { + // Take two chars + char firstChar = first.charAt(i); + char secondChar = second.charAt(i); + // Check if not equal + if (firstChar != secondChar) { + // Check their index position in map + if (map.get(firstChar) > map.get(secondChar)) { + // If first greater, means not sorted, so return true + return true; + } else { + // Else false + return false; + } + } + } + // If no chars mismatch and the length of the first is greater than second, not + // sorted, so return true else false + return (m > n); + } +} \ No newline at end of file