Sunday, 4 January 2026

Sliding Window Pattern – All Problems Explained (Java)

Sliding Window Pattern – All Problems with Step-by-Step Iteration (Java)

Sliding Window is a powerful technique to solve contiguous subarray and substring problems efficiently by avoiding repeated calculations.


Problem Statement

Given arrays and strings, solve multiple classic problems involving contiguous subarrays or substrings using fixed-size and variable-size sliding window techniques.

Examples:

Input: [2,1,5,1,3,2], k = 3
Output: Max Sum Subarray = 9

Input: "ADOBECODEBANC", "ABC"
Output: BANC

Approaches Used

  • Fixed Size Sliding Window
  • Variable Size Sliding Window

Java Code Implementation


import java.util.*;

public class SlidingWindowAllProblems {

    /* =====================================================
       1. Maximum Sum Subarray of Size K
       ===================================================== */
    static int maxSumSubarray(int[] arr, int k) {
        int sum = 0;
        for (int i = 0; i < k; i++) sum += arr[i];

        int max = sum;
        for (int i = k; i < arr.length; i++) {
            sum += arr[i] - arr[i - k];
            max = Math.max(max, sum);
        }
        return max;
    }

    /* =====================================================
       2. First Negative Number in Every Window
       ===================================================== */
    static void firstNegativeInWindow(int[] arr, int k) {
        Deque dq = new ArrayDeque<>();

        for (int i = 0; i < arr.length; i++) {
            if (arr[i] < 0) dq.addLast(i);

            if (!dq.isEmpty() && dq.peekFirst() <= i - k)
                dq.pollFirst();

            if (i >= k - 1)
                System.out.print(dq.isEmpty() ? "0 " : arr[dq.peekFirst()] + " ");
        }
        System.out.println();
    }

    /* =====================================================
       3. Count Distinct Elements in Every Window
       ===================================================== */
    static void countDistinct(int[] arr, int k) {
        Map map = new HashMap<>();

        for (int i = 0; i < k; i++)
            map.put(arr[i], map.getOrDefault(arr[i], 0) + 1);

        System.out.print(map.size() + " ");

        for (int i = k; i < arr.length; i++) {
            int left = arr[i - k];
            map.put(left, map.get(left) - 1);
            if (map.get(left) == 0) map.remove(left);

            map.put(arr[i], map.getOrDefault(arr[i], 0) + 1);
            System.out.print(map.size() + " ");
        }
        System.out.println();
    }

    /* =====================================================
       4. Average of Subarrays of Size K
       ===================================================== */
    static void averageSubarrays(int[] arr, int k) {
        int sum = 0;
        for (int i = 0; i < k; i++) sum += arr[i];

        System.out.print((double) sum / k + " ");

        for (int i = k; i < arr.length; i++) {
            sum += arr[i] - arr[i - k];
            System.out.print((double) sum / k + " ");
        }
        System.out.println();
    }

    /* =====================================================
       5. Maximum of All Subarrays of Size K
       ===================================================== */
    static void maxOfSubarrays(int[] arr, int k) {
        Deque dq = new ArrayDeque<>();

        for (int i = 0; i < arr.length; i++) {

            while (!dq.isEmpty() && arr[dq.peekLast()] <= arr[i])
                dq.pollLast();

            dq.addLast(i);

            if (dq.peekFirst() <= i - k)
                dq.pollFirst();

            if (i >= k - 1)
                System.out.print(arr[dq.peekFirst()] + " ");
        }
        System.out.println();
    }

    /* =====================================================
       6. Longest Substring Without Repeating Characters
       ===================================================== */
    static int longestUniqueSubstring(String s) {
        boolean[] freq = new boolean[256];
        int start = 0, max = 0;

        for (int end = 0; end < s.length(); end++) {
            while (freq[s.charAt(end)]) {
                freq[s.charAt(start)] = false;
                start++;
            }
            freq[s.charAt(end)] = true;
            max = Math.max(max, end - start + 1);
        }
        return max;
    }

    /* =====================================================
       7. Longest Substring with K Distinct Characters
       ===================================================== */
    static int longestKDistinct(String s, int k) {
        Map map = new HashMap<>();
        int start = 0, max = 0;

        for (int end = 0; end < s.length(); end++) {
            map.put(s.charAt(end), map.getOrDefault(s.charAt(end), 0) + 1);

            while (map.size() > k) {
                char left = s.charAt(start++);
                map.put(left, map.get(left) - 1);
                if (map.get(left) == 0) map.remove(left);
            }
            max = Math.max(max, end - start + 1);
        }
        return max;
    }

    /* =====================================================
       8. Smallest Subarray with Sum >= K
       ===================================================== */
    static int smallestSubarray(int[] arr, int k) {
        int start = 0, sum = 0, minLen = Integer.MAX_VALUE;

        for (int end = 0; end < arr.length; end++) {
            sum += arr[end];
            while (sum >= k) {
                minLen = Math.min(minLen, end - start + 1);
                sum -= arr[start++];
            }
        }
        return minLen == Integer.MAX_VALUE ? 0 : minLen;
    }

    /* =====================================================
       9. Minimum Window Substring
       ===================================================== */
    static String minWindow(String s, String t) {
        Map map = new HashMap<>();
        for (char c : t.toCharArray())
            map.put(c, map.getOrDefault(c, 0) + 1);

        int start = 0, count = map.size();
        int minLen = Integer.MAX_VALUE, minStart = 0;

        for (int end = 0; end < s.length(); end++) {
            char c = s.charAt(end);
            if (map.containsKey(c)) {
                map.put(c, map.get(c) - 1);
                if (map.get(c) == 0) count--;
            }

            while (count == 0) {
                if (end - start + 1 < minLen) {
                    minLen = end - start + 1;
                    minStart = start;
                }
                char left = s.charAt(start++);
                if (map.containsKey(left)) {
                    map.put(left, map.get(left) + 1);
                    if (map.get(left) > 0) count++;
                }
            }
        }
        return minLen == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLen);
    }

    /* =====================================================
       MAIN METHOD – MULTIPLE INPUTS
       ===================================================== */
    public static void main(String[] args) {

        System.out.println("Max Sum Subarray: " +
                maxSumSubarray(new int[]{2,1,5,1,3,2}, 3));

        System.out.print("First Negative: ");
        firstNegativeInWindow(new int[]{12,-1,-7,8,-15,30,16,28}, 3);

        System.out.print("Distinct Count: ");
        countDistinct(new int[]{1,2,1,3,4,2,3}, 4);

        System.out.print("Averages: ");
        averageSubarrays(new int[]{1,3,2,6,-1,4,1,8,2}, 5);

        System.out.print("Max of Subarrays: ");
        maxOfSubarrays(new int[]{1,3,-1,-3,5,3,6,7}, 3);

        System.out.println("Longest Unique Substring: " +
                longestUniqueSubstring("abcabcbb"));

        System.out.println("Longest K Distinct: " +
                longestKDistinct("aabacbebebe", 3));

        System.out.println("Smallest Subarray >= 7: " +
                smallestSubarray(new int[]{2,3,1,2,4,3}, 7));

        System.out.println("Minimum Window Substring: " +
                minWindow("ADOBECODEBANC", "ABC"));
    }
}



Explanation

1. Maximum Sum Subarray of Size K

Input: [2,1,5,1,3,2], k = 3

  • Initial window: [2,1,5] → sum = 8
  • Slide window → add 1, remove 2 → [1,5,1] → sum = 7
  • Slide window → add 3, remove 1 → [5,1,3] → sum = 9
  • Slide window → add 2, remove 5 → [1,3,2] → sum = 6

Output: 9


2. First Negative Number in Every Window

Input: [12,-1,-7,8,-15,30,16,28], k = 3

  • Window [12,-1,-7] → first negative = -1
  • Window [-1,-7,8] → first negative = -1
  • Window [-7,8,-15] → first negative = -7
  • Window [8,-15,30] → first negative = -15
  • Window [-15,30,16] → first negative = -15
  • Window [30,16,28] → no negative → 0

Output: -1 -1 -7 -15 -15 0


3. Count Distinct Elements in Every Window

Input: [1,2,1,3,4,2,3], k = 4

  • [1,2,1,3] → distinct = 3
  • [2,1,3,4] → distinct = 4
  • [1,3,4,2] → distinct = 4
  • [3,4,2,3] → distinct = 3

Output: 3 4 4 3


4. Average of Subarrays of Size K

Input: [1,3,2,6,-1,4,1,8,2], k = 5

  • [1,3,2,6,-1] → avg = 2.2
  • [3,2,6,-1,4] → avg = 2.8
  • [2,6,-1,4,1] → avg = 2.4
  • [6,-1,4,1,8] → avg = 3.6
  • [-1,4,1,8,2] → avg = 2.8

Output: 2.2 2.8 2.4 3.6 2.8


5. Maximum of All Subarrays of Size K

Input: [1,3,-1,-3,5,3,6,7], k = 3

  • [1,3,-1] → max = 3
  • [3,-1,-3] → max = 3
  • [-1,-3,5] → max = 5
  • [-3,5,3] → max = 5
  • [5,3,6] → max = 6
  • [3,6,7] → max = 7

Output: 3 3 5 5 6 7


6. Longest Substring Without Repeating Characters

Input: "abcabcbb"

  • "abc" → length 3
  • Repeat 'a' → shrink window
  • Continue maintaining unique window

Output: 3


7. Longest Substring with K Distinct Characters

Input: "aabacbebebe", k = 3

  • Expand window until > k distinct characters
  • Shrink window from left until condition is valid
  • Track max length during valid windows

Output: 7


8. Smallest Subarray with Sum ≥ K

Input: [2,3,1,2,4,3], k = 7

  • [2,3,1,2] → sum = 8 → shrink
  • [4,3] → sum = 7 → length = 2

Output: 2


9. Minimum Window Substring

Input: s = "ADOBECODEBANC", t = "ABC"

  • Expand window until all chars A, B, C included
  • Shrink window to minimize length
  • Smallest valid window = "BANC"

Output: BANC

Technique Used: Sliding Window (Fixed & Variable)


Sample Output

Max Sum Subarray: 9
First Negative: -1 -1 -7 -15 -15 0
Distinct Count: 3 4 4 3
Averages: 2.2 2.8 2.4 3.6 2.8
Max of Subarrays: 3 3 5 5 6 7
Longest Unique Substring: 3
Longest K Distinct: 7
Smallest Subarray >= 7: 2
Minimum Window Substring: BANC

Time & Space Complexity

Type Time Space
Sliding Window O(n) O(k)

Interview Tip

If the problem asks for a contiguous subarray or substring with constraints, Sliding Window should be your first optimization choice.


Practice More

  • Maximum vowels in a substring of size k
  • Longest subarray with at most k odd numbers

Category: Arrays, Strings
Difficulty: Easy → Medium
Techniques: Sliding Window, HashMap, Deque

Saturday, 3 January 2026

Naive Distinct Pattern Matching in Strings in Java

Naive Distinct Pattern Matching in Strings

An optimized version of naive pattern matching that skips unnecessary comparisons when the pattern contains all distinct characters.


Problem Statement

Given a text string txt and a pattern string pat (with all distinct characters), find and print all starting indices where the pattern occurs in the text.

Examples:

Input:
txt = "ABCABCD"
pat = "ABCD"

Output:
3

Input:
txt = "ABCEABCFABCD"
pat = "ABCD"

Output:
8

Approaches Used

  • Naive Pattern Matching
  • Naive Distinct Pattern Matching (Optimized)

Java Code Implementation


public class NaiveDistinctPatternMatching {

    public static void main(String[] args) {

        // Multiple test cases
        searchDistinctPattern("ABCABCD", "ABCD");        // Expected: 3
        searchDistinctPattern("ABCEABCFABCD", "ABCD");  // Expected: 8
        searchDistinctPattern("XYZABCDXYZ", "ABCD");    // Expected: 3
    }

    private static void searchDistinctPattern(String text, String pattern) {

        int n = text.length();
        int m = pattern.length();

        System.out.println("Text: " + text + ", Pattern: " + pattern);

        for (int i = 0; i <= n - m; ) {
            int j;

            // Match characters
            for (j = 0; j < m; j++) {
                if (text.charAt(i + j) != pattern.charAt(j)) {
                    break;
                }
            }

            // Full pattern matched
            if (j == m) {
                System.out.print(i + " ");
            }

            // Skip logic (key optimization)
            if (j == 0) {
                i++;
            } else {
                i = i + j;
            }
        }
        System.out.println("\n");
    }
}


Explanation

Approach 1: Naive Pattern Matching

  • Slide the pattern one character at a time.
  • Compare every character even if a mismatch occurs early.
  • Always increment index by 1.

Technique Used: Brute Force String Matching


Approach 2: Naive Distinct Pattern Matching

  • Works only when pattern characters are all distinct.
  • If a mismatch happens at index j, skip ahead by j characters.
  • Avoids rechecking characters that are guaranteed not to match.
  • Significantly reduces unnecessary comparisons.

Technique Used: Optimized Brute Force (Distinct Characters Optimization)


Sample Output

Text: ABCABCD, Pattern: ABCD
3

Text: ABCEABCFABCD, Pattern: ABCD
8

Text: XYZABCDXYZ, Pattern: ABCD
3

Time & Space Complexity

Approach Time Space
Naive Pattern Matching O((n - m + 1) × m) O(1)
Naive Distinct Pattern Matching O(n) O(1)

Interview Tip

Mention that this optimization works only when all characters in the pattern are distinct. Otherwise, use KMP for guaranteed linear performance.


Practice More

  • Compare Naive Distinct vs KMP with examples
  • Implement pattern matching using Z-algorithm

Category: Strings
Difficulty: Easy
Techniques: Brute Force, Pattern Matching, Optimization

Naive Pattern Matching (String Pattern Searching) in Java

Naive Pattern Matching (String Pattern Searching)

Find all occurrences of a pattern string within a given text using the simplest character-by-character comparison approach.


Problem Statement

Given a text string txt and a pattern string pat, print all starting indices where the pattern occurs in the text. The pattern must match completely and contiguously.

Examples:

Input:
txt = "ABABABCD"
pat = "ABAB"

Output:
0 2

Input:
txt = "ABCABCD"
pat = "ABCD"

Output:
3

Input:
txt = "AAAAA"
pat = "AAA"

Output:
0 1 2

Approaches Used

  • Naive Pattern Matching (Brute Force)

Java Code Implementation


public class NaivePatternMatching {

    public static void main(String[] args) {

        // Multiple test cases
        searchPattern("ABABABCD", "ABAB");   // Expected: 0 2
        searchPattern("ABCABCD", "ABCD");    // Expected: 3
        searchPattern("AAAAA", "AAA");       // Expected: 0 1 2
    }

    private static void searchPattern(String text, String pattern) {

        int n = text.length();
        int m = pattern.length();

        System.out.println("Text: " + text + ", Pattern: " + pattern);

        for (int i = 0; i <= n - m; i++) {
            int j;

            // Compare pattern with substring starting at i
            for (j = 0; j < m; j++) {
                if (text.charAt(i + j) != pattern.charAt(j)) {
                    break;
                }
            }

            // If full pattern matched
            if (j == m) {
                System.out.print(i + " ");
            }
        }
        System.out.println("\n");
    }
}


Explanation

Approach 1

  • Slide the pattern one character at a time over the text.
  • At each position, compare the pattern with the corresponding substring.
  • If all characters match, print the current index.
  • Continue until the remaining text length is less than the pattern length.

Technique Used: Brute Force / Naive String Matching


Sample Output

Text: ABABABCD, Pattern: ABAB
0 2

Text: ABCABCD, Pattern: ABCD
3

Text: AAAAA, Pattern: AAA
0 1 2

Time & Space Complexity

Approach Time Space
Naive Pattern Matching O((n - m + 1) × m) O(1)

Interview Tip

Always start with the naive approach in interviews, then optimize to KMP or Rabin–Karp when asked about performance improvements.


Practice More

  • Implement KMP Pattern Matching Algorithm
  • Pattern matching using Rabin–Karp (Rolling Hash)

Category: Strings
Difficulty: Easy
Techniques: Brute Force, String Matching

Find the Longest Common Prefix (Java)

Find the Longest Common Prefix (Java)

In this post, we will learn how to find the longest common prefix (LCP) among an array of strings. This is a common string manipulation problem often asked in coding interviews.


Problem Statement

Given an array of strings, find the longest prefix string that is common to all strings. If there is no common prefix, return an empty string.

Examples:

["flower","flow","flight"] → "fl"
["dog","racecar","car"] → ""
["interview","internet","internal"] → "inte"

Approach Used

  • Take the first string as the initial prefix
  • Compare it with each string in the array
  • If the current string does not start with the prefix, shorten the prefix
  • Repeat until the prefix fits all strings

Java Code Implementation


public class LongestCommonPrefix {

    public static void main(String[] args) {

        String[][] testCases = {
            {"flower","flow","flight"},
            {"dog","racecar","car"},
            {"interview","internet","internal"},
            {"apple","app","april"}
        };

        for(String[] arr : testCases){
            System.out.print("Strings: ");
            for(String s: arr) System.out.print(s + " ");
            System.out.println("\nLongest Common Prefix: " + longestCommonPrefix(arr));
            System.out.println();
        }
    }

    private static String longestCommonPrefix(String[] str) {

        if(str == null || str.length == 0) return "";

        String prefix = str[0];

        for(int i = 1; i < str.length; i++){
            while(str[i].indexOf(prefix) != 0){
                prefix = prefix.substring(0, prefix.length() - 1);
                if(prefix.isEmpty()) return "";
            }
        }

        return prefix;
    }
}


Explanation

Step-by-Step Approach

  • Assume the first string is the longest prefix initially
  • Compare with each string in the array
  • If the current string does not start with the prefix, remove the last character of the prefix
  • Continue until the prefix is common to all strings

Technique Used: Iterative Prefix Trimming


Sample Output

Strings: flower flow flight 
Longest Common Prefix: fl

Strings: dog racecar car 
Longest Common Prefix: 

Strings: interview internet internal 
Longest Common Prefix: inte

Strings: apple app april 
Longest Common Prefix: ap

Time & Space Complexity

Metric Complexity
Time O(N * M)
Space O(1)

Interview Tip

In interviews, this approach is preferred for its simplicity. For large datasets, Trie-based solutions can optimize prefix lookup.


Want to Practice More?

  • Find Longest Common Prefix using Divide and Conquer
  • Implement LCP using Trie data structure
  • Case-insensitive LCP

Category: Strings
Difficulty: Easy / Medium
Technique: Iterative, Prefix Trimming

Convert Roman Numeral to Integer (Java)

Convert Roman Numeral to Integer (Java)

In this post, we will learn how to convert a Roman numeral string into its integer value using Java. This solution efficiently handles both normal and subtractive cases using a single traversal.


Problem Statement

Given a Roman numeral string, convert it into its corresponding integer value.

Examples:

VIII   → 8
IX     → 9
LVIII  → 58
MCMXCIV → 1994

Approach Used

  • Traverse the string from right to left
  • Convert each Roman symbol to its integer value
  • Add or subtract values based on Roman numeral rules

Java Code Implementation


public class RomanToInteger {

    public static void main(String[] args) {

        String[] testCases = {
            "VIII",
            "IX",
            "LVIII",
            "MCMXCIV",
            "XL"
        };

        for (String roman : testCases) {
            System.out.println("Roman: " + roman +
                    " → Integer: " + romanToInteger(roman));
        }
    }

    private static int romanToInteger(String st) {

        int result = 0;
        int value = 0;

        for (int i = st.length() - 1; i >= 0; i--) {

            switch (st.charAt(i)) {
                case 'I': value = 1; break;
                case 'V': value = 5; break;
                case 'X': value = 10; break;
                case 'L': value = 50; break;
                case 'C': value = 100; break;
                case 'D': value = 500; break;
                case 'M': value = 1000; break;
            }

            if (value * 4 < result)
                result -= value;
            else
                result += value;
        }

        return result;
    }
}


Explanation

Right-to-Left Traversal

  • Roman numerals follow a subtractive rule (e.g., IV = 4)
  • By scanning from right to left, we can decide whether to add or subtract
  • If the current value is much smaller than the accumulated result, subtract it

Technique Used: Reverse Traversal + Greedy Decision


Sample Output

Roman: VIII → Integer: 8
Roman: IX → Integer: 9
Roman: LVIII → Integer: 58
Roman: MCMXCIV → Integer: 1994
Roman: XL → Integer: 40

Time & Space Complexity

Metric Complexity
Time O(n)
Space O(1)

Interview Tip

The right-to-left traversal avoids extra data structures and is often preferred in interviews for its simplicity and efficiency.


Want to Go Further?

  • Validate invalid Roman numerals
  • Convert Integer to Roman
  • Solve this using a HashMap approach

👉 Tip: This problem is commonly asked in coding interviews and tests understanding of greedy logic.


Category: Strings
Difficulty: Easy
Techniques: Greedy, Reverse Traversal

Check if One String Is a Subsequence of Another (Java)

Check if One String Is a Subsequence of Another (Java)

In this post, we will learn how to check whether one string is a subsequence of another string using Java. We will solve the problem using both iterative and recursive approaches and test it with multiple input cases.


What is a Subsequence?

A string s2 is a subsequence of string s1 if all characters of s2 appear in s1 in the same order, but not necessarily contiguously.

Examples:

ABCDEF & ADE   → Subsequence
ABCDEF & AEF   → Subsequence
ABCDEF & AED   → Not a Subsequence

Approaches Used

  • Iterative Approach: Two Pointer Technique
  • Recursive Approach: Compare last characters

Java Code Implementation


public class SubsequenceCheck {

    public static void main(String[] args) {

        String[][] testCases = {
            {"ABCDEF", "ADE"},
            {"ABCDEF", "AEF"},
            {"ABCDEF", "AED"},
            {"HELLO", "HLO"},
            {"HELLO", "OLL"}
        };

        for (String[] pair : testCases) {
            String s1 = pair[0];
            String s2 = pair[1];

            System.out.println("Main String: " + s1);
            System.out.println("Subsequence: " + s2);
            System.out.println("Iterative Check: " + isSubsequenceIterative(s1, s2));
            System.out.println("Recursive Check: " +
                    isSubsequenceRecursive(s1, s2, s1.length(), s2.length()));
            System.out.println();
        }
    }

    // Iterative approach using two pointers
    private static boolean isSubsequenceIterative(String s1, String s2) {

        int j = 0;

        for (int i = 0; i < s1.length() && j < s2.length(); i++) {
            if (s1.charAt(i) == s2.charAt(j)) {
                j++;
            }
        }
        return j == s2.length();
    }

    // Recursive approach
    private static boolean isSubsequenceRecursive(String s1, String s2, int n, int m) {

        if (m == 0)
            return true;

        if (n == 0)
            return false;

        if (s1.charAt(n - 1) == s2.charAt(m - 1))
            return isSubsequenceRecursive(s1, s2, n - 1, m - 1);
        else
            return isSubsequenceRecursive(s1, s2, n - 1, m);
    }
}


Explanation

1. Iterative Approach (Two Pointer Technique)

  • Initialize two pointers for both strings
  • Traverse the main string character by character
  • Move the second pointer only when characters match
  • If all characters of second string are matched, it is a subsequence

Technique Used: Two Pointer Technique


2. Recursive Approach

  • If the second string becomes empty, return true
  • If the first string becomes empty first, return false
  • Compare last characters and reduce the problem size

Technique Used: Recursion


Sample Output

Main String: ABCDEF
Subsequence: ADE
Iterative Check: true
Recursive Check: true

Main String: ABCDEF
Subsequence: AED
Iterative Check: false
Recursive Check: false

Time & Space Complexity

Approach Time Complexity Space Complexity
Iterative O(n) O(1)
Recursive O(n) O(n) (Recursion Stack)

Interview Tip

In interviews, the iterative two pointer approach is preferred because it avoids recursion overhead and uses constant extra space.


Want to Go Further?

To deepen your understanding, try solving these variations:

  • Check subsequence in a case-insensitive manner
  • Count how many times a subsequence appears
  • Longest Common Subsequence (LCS)

👉 Tip: This problem is a foundation for many advanced DP problems.


Category: Strings
Difficulty: Easy
Technique: Two Pointers, Recursion

Check if Two Strings Are Anagrams (Java)

 

Check if Two Strings Are Anagrams (Java)

In this post, we will learn how to check whether two strings are anagrams of each other using Java. We will solve the problem using two different techniques and test it with multiple input strings.


What is an Anagram?

Two strings are called anagrams if they contain the same characters with the same frequencies, but possibly in a different order.

Examples:

listen  & silent  → Anagram
letm    & metl    → Anagram
hello   & world   → Not an Anagram

Approaches Used

  • Naive Approach: Sort both strings and compare
  • Efficient Approach: Frequency Count using array

Java Code Implementation


import java.util.Arrays;

public class AnagramCheck {

    static final int CHAR = 256;

    public static void main(String[] args) {

        String[][] testCases = {
            {"letm", "metl"},
            {"listen", "silent"},
            {"hello", "world"},
            {"triangle", "integral"}
        };

        for (String[] pair : testCases) {
            String s1 = pair[0];
            String s2 = pair[1];

            System.out.println("Strings: " + s1 + " , " + s2);
            System.out.println("Naive Check: " + isAnagramNaive(s1, s2));
            System.out.println("Efficient Check: " + isAnagramEfficient(s1, s2));
            System.out.println();
        }
    }

    // Naive approach using sorting
    private static boolean isAnagramNaive(String s1, String s2) {

        if (s1.length() != s2.length())
            return false;

        char[] a1 = s1.toCharArray();
        char[] a2 = s2.toCharArray();

        Arrays.sort(a1);
        Arrays.sort(a2);

        return Arrays.equals(a1, a2);
    }

    // Efficient approach using frequency count
    private static boolean isAnagramEfficient(String s1, String s2) {

        if (s1.length() != s2.length())
            return false;

        int[] count = new int[CHAR];

        for (int i = 0; i < s1.length(); i++) {
            count[s1.charAt(i)]++;
            count[s2.charAt(i)]--;
        }

        for (int i = 0; i < CHAR; i++) {
            if (count[i] != 0)
                return false;
        }
        return true;
    }
}


Explanation

1. Naive Approach (Sorting Technique)

  • Convert both strings to character arrays
  • Sort both arrays
  • If sorted arrays are equal, the strings are anagrams

Technique Used: Sorting


2. Efficient Approach (Frequency Count)

  • Create a frequency array of size 256 (ASCII characters)
  • Increment count for characters of first string
  • Decrement count for characters of second string
  • If all values are zero, strings are anagrams

Technique Used: Frequency Count / Hashing using Array


Sample Output

Strings: letm , metl
Naive Check: true
Efficient Check: true

Strings: listen , silent
Naive Check: true
Efficient Check: true

Strings: hello , world
Naive Check: false
Efficient Check: false

Time & Space Complexity

Approach Time Complexity Space Complexity
Naive (Sorting) O(n log n) O(n)
Efficient (Frequency Count) O(n) O(1)

Interview Tip

The frequency count approach is preferred in interviews because it runs in linear time and avoids sorting overhead.


Optimization Note

If the strings contain only lowercase alphabets (a to z), a frequency array of size 26 can be used instead of 256.


Category: Strings
Difficulty: Easy
Technique: Sorting, Frequency Count

Check if a String is Palindrome (Java)

Check if a String is Palindrome (Java)

In this post, we will learn how to check whether a given string is a palindrome using Java. We will solve the problem using two different techniques and handle multiple input strings.


What is a Palindrome?

A string is called a palindrome if it reads the same forward and backward.

Examples:

ABCBA  → Palindrome
MADAM  → Palindrome
HELLO  → Not a Palindrome

Approaches Used

  • Naive Approach: Reverse the string and compare
  • Efficient Approach: Two Pointer Technique

Java Code Implementation


public class StringPalindrome {

    public static void main(String[] args) {

        String[] inputs = {"ABCBA", "MADAM", "HELLO", "LEVEL"};

        for (String str : inputs) {
            System.out.println("String: " + str);
            System.out.println("Naive Check: " + isPalindromeNaive(str));
            System.out.println("Efficient Check: " + isPalindromeEfficient(str));
            System.out.println();
        }
    }

    // Naive approach using reverse
    private static boolean isPalindromeNaive(String str) {
        StringBuilder reverse = new StringBuilder(str);
        reverse.reverse();
        return str.equals(reverse.toString());
    }

    // Efficient approach using two pointers
    private static boolean isPalindromeEfficient(String str) {

        int left = 0;
        int right = str.length() - 1;

        while (left < right) {
            if (str.charAt(left) != str.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}


Explanation

1. Naive Approach (Reverse String)

  • Reverse the given string
  • Compare it with the original string
  • If both are equal, the string is a palindrome

Technique Used: String Reversal


2. Efficient Approach (Two Pointer Technique)

  • Initialize two pointers: one at the start and one at the end
  • Compare characters at both pointers
  • Move pointers inward until they cross
  • If all characters match, it is a palindrome

Technique Used: Two Pointer Technique


Sample Output

String: ABCBA
Naive Check: true
Efficient Check: true

String: MADAM
Naive Check: true
Efficient Check: true

String: HELLO
Naive Check: false
Efficient Check: false

Time & Space Complexity

Approach Time Complexity Space Complexity
Naive O(n) O(n)
Efficient O(n) O(1)

Interview Tip

In interviews, the Two Pointer Technique is preferred because it uses constant extra space and is more efficient.


Category: Strings
Difficulty: Easy
Technique: Two Pointers

Given a string, find the frequency of each character present in it.

Frequency Count of Characters in a String (Java)

In this post, we will learn how to find the frequency of each character present in a string using Java.


Problem Statement

Given a string, print the frequency of every character present in it.

Input:

java2bigdatablogspotdotcom

Approach

  • The string contains alphabets and digits.
  • So, we cannot use a frequency array of size 26.
  • We use an array of size 256 to store ASCII character frequencies.
  • Each character’s ASCII value is used as an index.

Java Code Implementation


public class FreqStringCount {

    public static void main(String[] args) {

        String stg = "java2bigdatablogspotdotcom";
        int[] count = new int[256]; // ASCII size

        // Count frequency of each character
        for (int i = 0; i < stg.length(); i++) {
            count[stg.charAt(i)]++;
        }

        // Print character frequencies
        for (int i = 0; i < 256; i++) {
            if (count[i] > 0) {
                System.out.println((char) i + " " + count[i]);
            }
        }
    }
}


Explanation

  1. We create an integer array of size 256 to cover all ASCII characters.
  2. We traverse the string character by character.
  3. Each character is converted to its ASCII value automatically.
  4. The frequency is increased using the ASCII value as the index.

Example:

'j' → ASCII 106 → count[106]++
'2' → ASCII 50  → count[50]++

Sample Output (Partial)

j 1
a 4
v 1
2 1
b 2
g 2
d 2
o 4
t 4
c 1
m 1

Time & Space Complexity

  • Time Complexity: O(n)
  • Space Complexity: O(1) (Fixed size array of 256)

Optimization Note

Note: If the string contains only lowercase alphabets (a to z), we can optimize the solution by using a count array of size 26 instead of 256.


Category: Strings
Difficulty: Easy
Concept: Character Frequency Count