1. Insert and search words in a trie data structure.
Solution:
public class Trie {
// Alphabet size (# of symbols)
static final int ALPHABET_SIZE = 26;
// trie node
static class TrieNode
{
TrieNode[] children = new TrieNode[ALPHABET_SIZE];
// isEndOfWord is true if the node represents
// end of a word
boolean isEndOfWord;
TrieNode(){
isEndOfWord = false;
for (int i = 0; i < ALPHABET_SIZE; i++)
children[i] = null;
}
};
static TrieNode root;
// If not present, inserts key into trie
// If the key is prefix of trie node,
// just marks leaf node
static void insert(String key)
{
int level;
int length = key.length();
int index;
TrieNode pCrawl = root;
for (level = 0; level < length; level++)
{
index = key.charAt(level) - 'a';
if (pCrawl.children[index] == null)
pCrawl.children[index] = new TrieNode();
pCrawl = pCrawl.children[index];
}
// mark last node as leaf
pCrawl.isEndOfWord = true;
}
// Returns true if key presents in trie, else false
static boolean search(String key)
{
int level;
int length = key.length();
int index;
TrieNode pCrawl = root;
for (level = 0; level < length; level++)
{
index = key.charAt(level) - 'a';
if (pCrawl.children[index] == null)
return false;
pCrawl = pCrawl.children[index];
}
return (pCrawl.isEndOfWord);
}
}//class closed
Insertion:
TC: O(n)
SC: O(n*m)
Searching:
TC: O(n)
SC: O(1)
2. Given an array of strings words, find the longest string in words such that every prefix of it
is also in words. Return the string described above. If there is more than one string with
the same length, return the lexicographically smallest one, and if no string exists, return
"".
Input: words = ["k","ki","kir","kira", "kiran", “cricket”]
Output: "kiran"
Explanation: "kiran" has prefixes "kira", "kir", "ki", and "k", and all of them appear in
words.
Solution:
class Trie {
Trie[] children = new Trie[128];
boolean isWord;
class Solution {
Trie root = new Trie();
String res = "";
public String longestWord(String[] words) {
for (String word : words) addWord(word);
for (String word : words) searchPrefix(word);
return res;
private void searchPrefix(String word) {
Trie cur = root;
for (char c : word.toCharArray()) {
cur = cur.children[c];
if (!cur.isWord) return;
if (res.length() < word.length() ||
res.length() == word.length() && res.compareTo(word) > 0) res = word;
}// searchPrefix function closed
private void addWord(String word) {
Trie cur = root;
for(char c : word.toCharArray()) {
if (cur.children[c] == null) cur.children[c] = new Trie();
cur = cur.children[c];
cur.isWord = true;
}// addWord function closed
}// class closed
3. Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a
space-separated sequence of one or more dictionary words.
Note that the same word in the dictionary may be reused multiple times in the
segmentation.
Input: s = "applepenapple", wordDict = ["apple","pen"]
Output: true
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
Note that you are allowed to reuse a dictionary word.
Input: s = "catsandog", wordDict = ["cats","dog","sand","and","cat"]
Output: false
Solution:
class TrieNode{
TrieNode[] children;
boolean isWord;
public TrieNode(){
children = new TrieNode[26];
isWord = false;
}
}
public boolean wordBreak(String s, List<String> wordDict) {
TrieNode t = new TrieNode();
for(String word:wordDict){
insertString(word, t);
}
return helper(s.toCharArray(), 0, t);
public boolean helper(char[] charArray, int startIndex, TrieNode root){
Queue<TrieNode> queue = new LinkedList<>();
queue.add(root);
boolean[] visited = new boolean[charArray.length];
while(!queue.isEmpty() && startIndex < charArray.length) {
int size = queue.size();
for(int i=0;i<size;i++){
TrieNode t = queue.poll();
if(t.children[charArray[startIndex]-'a'] != null)
{
queue.add(t.children[charArray[startIndex]-'a']);
if(t.children[charArray[startIndex]-'a'].isWord && !visited[startIndex])
{
queue.add(root);
visited[startIndex] = true;
}//if closed
}//if closed
}//for loop closed
if(queue.size() != 0)
startIndex++;
}//while loop closed
if(startIndex == charArray.length && visited[startIndex-1]){
return true;
}
return false;
}//helper function closed
public void insertString(String s, TrieNode t){
char[] charArray = s.toCharArray();
for(int i=0;i<charArray.length;i++) {
if(t.children[charArray[i]-'a'] == null){
t.children[charArray[i]-'a'] = new TrieNode();
}
t = t.children[charArray[i]-'a'];
t.isWord = true;
4. Find duplicate rows present in a given binary matrix by traversing the matrix
only once.
Input:
[1 0 0 1 0]
[0 1 1 0 0]
[1 0 0 1 0]
[0 0 1 1 0]
[0 1 1 0 0]
Output: {3, 5}
Explanation: Row #3 is duplicate of row #1 and row #5 is duplicate of row #2
Solution:
// A class to store a Trie node
class Trie
{
boolean isLeaf; // set when the node is a leaf node
Trie[] character = new Trie[2];
// Constructor
Trie() {
isLeaf = false;
}
}
class Main
{
// Iterative function to insert each array element into a Trie
public static boolean insert(Trie head, int[] A)
{
// start from the root node
Trie curr = head;
for (int i: A)
{
// create a new node if the path doesn't exist
if (curr.character[i] == null) {
curr.character[i] = new Trie();
}
// go to the next node
curr = curr.character[i];
}
// if the row is inserted before, return false
if (curr.isLeaf) {
return false;
}
// mark leaf node and return true
return (curr.isLeaf = true);
}
public static void main (String[] args)
{
Trie head = new Trie();
int mat[][] =
{
{1, 0, 0, 1, 0},
{0, 1, 1, 0, 0},
{1, 0, 0, 1, 0},
{0, 0, 1, 1, 0},
{0, 1, 1, 0, 0}
};
// insert all rows of the matrix into a Trie
for (int i = 0; i < mat.length; i++)
{
if (!insert(head, mat[i])) {
System.out.println("Duplicate row found: Row #" + (i + 1));
}
}
}
}
TC: O(m*n)
SC: O(m*n)