Problems - Set 1
Easy
Word Match
Design a method to find the frequency of occurrences of any given word in a book.
Approach 1: Using string split (One time)
package algo;
public class Problem1 {
public static void main(String[] args) {
String bookText = "Java is great. Java is powerful. Java is everywhere!";
String word = "Java";
int freq = getWordFrequency(bookText, word); // Output: 3
System.out.println(freq);
}
public static int getWordFrequency(String bookText, String word) {
if (bookText == null || word == null || word.isEmpty()) {
return 0;
}
String[] words = bookText.toLowerCase().split("\\W+"); // split on non-word characters
int count = 0;
for (String w : words) {
if (w.equals(word.toLowerCase())) {
count++;
}
}
return count;
}
}Approach 2: Using StringUtils method
package algo;
import org.apache.commons.lang3.StringUtils;
public class Problem1 {
public static void main(String[] args) {
String bookText = "Java is great. Java is powerful. Java is everywhere!";
String word = "java";
System.out.println(StringUtils.countMatches(bookText.toLowerCase(), word.toLowerCase()));
}
}
Approach 3: Optimized for Multiple Calls
Preprocess the book text once into a frequency map. Then lookups are fast.
package algo;
import java.util.HashMap;
import java.util.Map;
public class WordFrequencyAnalyser {
private final Map<String, Integer> wordFrequencyMap;
public WordFrequencyAnalyser(String bookText) {
wordFrequencyMap = new HashMap<>();
preprocess(bookText);
}
private void preprocess(String bookText) {
if (bookText == null) {
return;
}
String[] words = bookText.toLowerCase().split("\\W+"); // non-word character split
for (String word : words) {
if (!word.isEmpty()) {
wordFrequencyMap.put(word, wordFrequencyMap.getOrDefault(word, 0) + 1);
}
}
}
public int getFrequency(String word) {
if (word == null || word.isEmpty()) {
return 0;
}
return wordFrequencyMap.getOrDefault(word.toLowerCase(), 0);
}
}package algo;
public class Problem1 {
public static void main(String[] args) {
String bookText = "Java is great. Java is powerful. Java is everywhere!";
WordFrequencyAnalyser analyzer = new WordFrequencyAnalyser(bookText);
System.out.println(analyzer.getFrequency("java")); // Output: 3
System.out.println(analyzer.getFrequency("is")); // Output: 3
System.out.println(analyzer.getFrequency("powerful")); // Output: 1
System.out.println(analyzer.getFrequency("python")); // Output: 0
}
}Medium
Pattern Matching
We are given:
A pattern string, e.g.,
"aabab"A value string, e.g.,
"catcatgocatgo"
We need to return true if we can map each unique character (a or b) in the pattern to a non-empty substring in the value so that replacing the pattern with its mapped substrings gives the original value.
Example
Pattern:
"aabab"Value:
"catcatgocatgo"
Let’s say
'a' = "cat"'b' = "go"
Substituting:
Pattern → "a a b a b" → "cat cat go cat go" → matches value → return true.
Constraints
Each
aandbmust map to one consistent substring throughout the pattern.aandbmust be different (but may be of any length).We can’t have
a = ""orb = ""(empty string is not allowed).
Approach
Count how many times
aandbappear in the pattern.Try all possible lengths of the substring assigned to
a.For each possible length of
a, calculate the length ofb(from remaining length of value).Try assigning substrings to
aandband check if the pattern reconstructs to the value.If we find a match, return
true. Otherwise returnfalse.
public class PatternMatcher {
public static boolean doesMatch(String pattern, String value) {
if (pattern.length() == 0) return value.length() == 0;
// Normalize pattern so that it starts with 'a'
char firstChar = pattern.charAt(0);
boolean isSwapped = false;
if (firstChar != 'a') {
pattern = swapPattern(pattern);
isSwapped = true;
}
int countA = countOf(pattern, 'a');
int countB = pattern.length() - countA;
int maxLenA = value.length() / Math.max(1, countA); // Avoid divide by zero
for (int lenA = 0; lenA <= maxLenA; lenA++) {
int remainingLength = value.length() - lenA * countA;
if (countB == 0) {
if (remainingLength != 0) continue;
if (isMatch(pattern, value, lenA, 0, isSwapped)) return true;
} else if (remainingLength % countB == 0) {
int lenB = remainingLength / countB;
if (isMatch(pattern, value, lenA, lenB, isSwapped)) return true;
}
}
return false;
}
private static boolean isMatch(String pattern, String value, int lenA, int lenB, boolean isSwapped) {
int index = 0;
String aStr = null;
String bStr = null;
for (char c : pattern.toCharArray()) {
int len = (c == 'a') ? lenA : lenB;
if (index + len > value.length()) return false;
String sub = value.substring(index, index + len);
if (c == 'a') {
if (aStr == null) aStr = sub;
else if (!aStr.equals(sub)) return false;
} else {
if (bStr == null) bStr = sub;
else if (!bStr.equals(sub)) return false;
}
index += len;
}
if (aStr != null && aStr.equals(bStr)) return false;
return true;
}
private static int countOf(String pattern, char c) {
int count = 0;
for (char ch : pattern.toCharArray()) {
if (ch == c) count++;
}
return count;
}
private static String swapPattern(String pattern) {
char[] swapped = new char[pattern.length()];
for (int i = 0; i < pattern.length(); i++) {
swapped[i] = pattern.charAt(i) == 'a' ? 'b' : 'a';
}
return new String(swapped);
}
public static void main(String[] args) {
System.out.println(doesMatch("aabab", "catcatgocatgo")); // true
System.out.println(doesMatch("aaaa", "catcatcatcat")); // true
System.out.println(doesMatch("abab", "redblueredblue")); // true
System.out.println(doesMatch("aabb", "xyzabcxzyabc")); // false
}
}Arithmetic Evaluation
Given an arithmetic equation consisting of positive integers, +, -, * and / and no parentheses. Compute the result.
To evaluate an arithmetic expression like 2*3+5/6*3+15 (with no parentheses, only +, -, *, and /, and all positive integers), we must obey the order of operations:
Operator Precedence (BODMAS):
*and/(left to right)+and-(left to right)
public class ArithmeticEvaluator {
public static double evaluate(String expression) {
// Store numbers and the last operator
double currentNumber = 0;
char operation = '+'; // Assume '+' before first number
double result = 0;
double lastTerm = 0; // For handling * and / first
int n = expression.length();
for (int i = 0; i < n; i++) {
char ch = expression.charAt(i);
// If digit or decimal, build the number
if (Character.isDigit(ch) || ch == '.') {
int start = i;
while (i < n && (Character.isDigit(expression.charAt(i)) || expression.charAt(i) == '.')) {
i++;
}
currentNumber = Double.parseDouble(expression.substring(start, i));
i--; // adjust i because it will be incremented in the for-loop
}
// If current character is operator or we are at the end of the expression
if (!Character.isDigit(ch) && ch != ' ' && ch != '.' || i == n - 1) {
switch (operation) {
case '+':
result += lastTerm;
lastTerm = currentNumber;
break;
case '-':
result += lastTerm;
lastTerm = -currentNumber;
break;
case '*':
lastTerm = lastTerm * currentNumber;
break;
case '/':
lastTerm = lastTerm / currentNumber;
break;
}
operation = ch; // update the current operation
}
}
// Add the last processed term
result += lastTerm;
return result;
}
public static void main(String[] args) {
String expr = "2*3+5/6*3+15";
System.out.println("Result: " + evaluate(expr)); // Output: 23.5
}
}
Initialize:
result = 0lastTerm = 0operation = '+'
Read
2Operation is
'+', solastTerm = 2
* 3:Operation is
*, solastTerm = 2 * 3 = 6
+ 5:Add
lastTerm (6)toresult:result = 6Set
lastTerm = 5
/ 6:lastTerm = 5 / 6 ≈ 0.8333
* 3:lastTerm = 0.8333 * 3 ≈ 2.5
+ 15:Add
lastTerm (2.5)toresult:result = 6 + 2.5 = 8.5Set
lastTerm = 15
End of string → Add
lastTerm (15)to result → Final:8.5 + 15 = 23.5
This matches what BODMAS expects:
2 * 3 = 6
5 / 6 = 0.8333
0.8333 * 3 = 2.5
Final: 6 + 2.5 + 15 = 23.5Last updated