Skip to content

Commit

Permalink
add: variable size window slide java examples
Browse files Browse the repository at this point in the history
  • Loading branch information
thutasann committed Feb 8, 2025
1 parent d62cbdc commit fbe2b55
Show file tree
Hide file tree
Showing 2 changed files with 233 additions and 22 deletions.
108 changes: 86 additions & 22 deletions data_structures/docs/keys-patterns.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,109 @@
# Key patterns
# Key Patterns in Data Structures and Algorithms

## A. Sliding Window

When to Use: Subarray problems (e.g., maximum sum, longest substring).
Key Idea: Expand/shrink the window based on conditions.
Example: Longest Substring Without Repeating Characters
- **When to Use:** Subarray problems (e.g., maximum sum, longest substring).
- **Key Idea:** Expand/shrink the window based on conditions.
- **Example:** Longest Substring Without Repeating Characters

## B. Two Pointers

When to Use: Sorted arrays or lists (e.g., finding pairs).
Key Idea: Use two pointers to narrow down the search space.
Example: Two Sum II - Input Array Is Sorted
- **When to Use:** Sorted arrays or lists (e.g., finding pairs).
- **Key Idea:** Use two pointers to narrow down the search space.
- **Example:** Two Sum II - Input Array Is Sorted

## C. Hash Maps

When to Use: Fast lookups (e.g., frequency count, duplicates).
Key Idea: Store data in key-value pairs to optimize searches.
Example: Two Sum
- **When to Use:** Fast lookups (e.g., frequency count, duplicates).
- **Key Idea:** Store data in key-value pairs to optimize searches.
- **Example:** Two Sum

## D. Binary Search

When to Use: Search problems in sorted arrays.
Key Idea: Divide and conquer to find the target efficiently.
Example: Binary Search
- **When to Use:** Search problems in sorted arrays.
- **Key Idea:** Divide and conquer to find the target efficiently.
- **Example:** Binary Search

## E. Backtracking

When to Use: Recursive exploration (e.g., permutations, combinations).
Key Idea: Explore all possibilities and backtrack when conditions fail.
Example: N-Queens
- **When to Use:** Recursive exploration (e.g., permutations, combinations).
- **Key Idea:** Explore all possibilities and backtrack when conditions fail.
- **Example:** N-Queens

## F. Dynamic Programming

When to Use: Optimization problems with overlapping subproblems.
Key Idea: Solve smaller subproblems, store results (memoization/tabulation).
Example: Climbing Stairs
- **When to Use:** Optimization problems with overlapping subproblems.
- **Key Idea:** Solve smaller subproblems, store results (memoization/tabulation).
- **Example:** Climbing Stairs

## G. Graphs

When to Use: Problems involving connections (e.g., shortest path).
Key Idea: Use BFS, DFS, or Dijkstra’s Algorithm.
Example: Clone Graph
- **When to Use:** Problems involving connections (e.g., shortest path).
- **Key Idea:** Use BFS, DFS, or Dijkstra’s Algorithm.
- **Example:** Clone Graph

## H. Deque

- **When to Use:** Problems requiring efficient insertions and deletions from both ends.
- **Key Idea:** Use a double-ended queue to manage elements.
- **Example:** Sliding Window Maximum

## I. Greedy Algorithms

- **When to Use:** Problems where a locally optimal choice leads to a globally optimal solution.
- **Key Idea:** Make the best choice at each step and build a solution piece by piece.
- **Example:** Activity Selection Problem

## J. Union-Find (Disjoint Set)

- **When to Use:** Problems involving dynamic connectivity and finding connected components.
- **Key Idea:** Use a data structure to efficiently merge sets and find representatives.
- **Example:** Kruskal's Algorithm for Minimum Spanning Tree

## K. Trees and Traversals

- **When to Use:** Hierarchical data structures (e.g., XML parsing, file systems).
- **Key Idea:** Use different traversal methods (in-order, pre-order, post-order) to visit nodes.
- **Example:** Binary Tree Inorder Traversal

## L. Heaps and Priority Queues

- **When to Use:** Problems requiring frequent access to the minimum/maximum element.
- **Key Idea:** Use a binary heap to efficiently perform insertions and deletions.
- **Example:** Merge K Sorted Lists

## M. Bit Manipulation

- **When to Use:** Problems involving binary operations or optimizations at the bit level.
- **Key Idea:** Use bitwise operators to perform operations directly on bits for efficiency.
- **Example:** Single Number (finding unique element in a list where every other element appears twice)

## N. Segment Trees and Fenwick Trees

- **When to Use:** Range query problems (e.g., sum, minimum) and updates.
- **Key Idea:** Use trees to efficiently store and calculate range-based queries.
- **Example:** Range Sum Query

## O. Tries

- **When to Use:** Problems involving prefix searches, autocomplete, and dictionaries.
- **Key Idea:** Use a tree-like structure to store strings by character.
- **Example:** Implement Trie (Prefix Tree)

## P. Advanced Graph Algorithms

- **When to Use:** More complex graph problems (e.g., network flow, strongly connected components).
- **Key Idea:** Use specialized algorithms like Ford-Fulkerson, Kosaraju's, or Tarjan's.
- **Example:** Maximum Flow in a Flow Network

## Q. Mathematical Algorithms

- **When to Use:** Problems involving mathematical computations, number theory, or combinatorics.
- **Key Idea:** Use properties of numbers (e.g., primes, greatest common divisors) and combinatorial counting.
- **Example:** Sieve of Eratosthenes for Prime Numbers

## R. Randomized Algorithms

- **When to Use:** Problems where a probabilistic solution is more efficient.
- **Key Idea:** Use randomness to achieve good average-case performance.
- **Example:** Quickselect for finding kth smallest element
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,153 @@ public static void main(String[] args) {
smallestSubArrayWithGivenSum();
longestSubstringWithKDistinct();
dynamicWindowSum();
dynamicWindowDistinct();
longestSubArrayWithSum();
minimumWindowSubstring();
longestSubStringWithoutRepeatingCharacter();
}

public static void longestSubStringWithoutRepeatingCharacter() {
System.out.println("\nLongest SubString without repeating character ==> ");
String str = "abcabcbb";
int windowStart = 0, maxLength = 0;
Map<Character, Integer> charIndexMap = new HashMap<>();

for (int windowEnd = 0; windowEnd < str.length(); windowEnd++) {
char rightChar = str.charAt(windowEnd);

if (charIndexMap.containsKey(rightChar)) {
windowStart = Math.max(windowStart, charIndexMap.get(rightChar) + 1);
}

charIndexMap.put(rightChar, windowEnd);
maxLength = Math.max(maxLength, windowEnd - windowStart + 1);
}

System.out.println("maxLength ==> " + maxLength);
}

/**
* Minimum Window Substring
* - Given a string `s` and a string `t`, return the minimum window in `s` which
* contain all the characters in `t`. if there is no such window in `s` that
* covers all characters in `t`, return empty string.
*
* Approach
* - Use Two Maps: One for counting characters in t (tMap) and one for the
* current window (windowMap)
* - Expand the window: Move (windowEnd) to include more characters until all
* characters from t are included.
* - Shrink the window: Once all characters are include, try to minimize the
* window size by moving windowStart.
* - Track the Minimum Window: Update the minimum window size when a valid
* window is found.
*/
public static void minimumWindowSubstring() {
System.out.println("\nMinimum Window Substring ==> ");
String s = "ADOBECODEBANC";
String t = "ABC";
if (s.length() == 0 || t.length() == 0) {
System.out.println("Invalid Inputs");
}

Map<Character, Integer> tMap = new HashMap<>();
for (char c : t.toCharArray()) {
tMap.put(c, tMap.getOrDefault(c, 0) + 1);
}

Map<Character, Integer> windowMap = new HashMap<>();
int windowStart = 0, minLength = Integer.MAX_VALUE, minStart = 0;
int matches = 0;

for (int windowEnd = 0; windowEnd < s.length(); windowEnd++) {
char rightChar = s.charAt(windowEnd);
windowMap.put(rightChar, windowMap.getOrDefault(rightChar, 0) + 1);

if (tMap.containsKey(rightChar) && windowMap.get(rightChar).equals(tMap.get(rightChar))) {
matches++;
}

while (matches == tMap.size()) {

if (windowEnd - windowStart + 1 < minLength) {
minLength = windowEnd - windowStart + 1;
minStart = windowStart;
}

char leftChar = s.charAt(windowStart);
windowMap.put(leftChar, windowMap.getOrDefault(leftChar, 0) - 1);

if (tMap.containsKey(leftChar) && windowMap.get(leftChar) < tMap.get(leftChar)) {
matches--;
}

windowStart++;
}
}

String ans = minLength == Integer.MAX_VALUE ? "" : s.substring(minStart, minStart + minLength);
System.out.println("ans ==> " + ans);
}

/**
* Longest Subarray with Sum at Most `S`
* - Given an array of positive integers and a positive integer `S`, find the
* length of the longest subarray that sums to at most `S`
*
* Approach
* - Initialize: Start with two pointers (`windowstart` and `windowEnd`) and a
* variable to keep track of the current sum (`windowSum`)
* - Expand the Window: Iterate over the array with `windowEnd` to add element
* to `windowSum`
* - Shrink the Window: if the windowSum exceeds S, increment windowStart to
* reduce the sum until it is less than or equal to S
* - Track maximum length: During each valid window, calculate the window's
* length and update maxLength found
*/
public static void longestSubArrayWithSum() {
System.out.println("\nLongest Subarray with Sum at Most S ==> ");
int[] arr = { 3, 1, 2, 1, 1, 1, 1, 2 };
int S = 5;

int windowStart = 0, windowSum = 0, maxLength = 0;

for (int windowEnd = 0; windowEnd < arr.length; windowEnd++) {
windowSum += arr[windowEnd];

while (windowSum >= S) {
windowSum -= arr[windowStart];
windowStart++;
}

maxLength = Math.max(maxLength, windowEnd - windowStart + 1);
}

System.out.println("maxLength ==> " + maxLength);
}

public static void dynamicWindowDistinct() {
System.out.println("\nDynamic Window Distinct ==> ");
String str = "aabacbebebe";
int maxDistinct = 2;
int windowStart = 0;
HashMap<Character, Integer> charFrequencyMap = new HashMap<>();

for (int windowEnd = 0; windowEnd < str.length(); windowEnd++) {
char rightChar = str.charAt(windowEnd);
charFrequencyMap.put(rightChar, charFrequencyMap.getOrDefault(rightChar, 0) + 1);

while (charFrequencyMap.size() > maxDistinct) {
System.out.println("Current window with more than " + maxDistinct + " distinct characters: "
+ str.substring(windowStart, windowEnd));
char leftChar = str.charAt(windowStart);
charFrequencyMap.put(leftChar, charFrequencyMap.get(leftChar) - 1);
if (charFrequencyMap.get(leftChar) == 0) {
charFrequencyMap.remove(leftChar);
}
windowStart++;
}
}
}

public static void dynamicWindowSum() {
Expand Down

0 comments on commit fbe2b55

Please sign in to comment.