Advanced Algorithmic
Problem Solving
(R1UC601B)
RAJAT SACHAN
22SCSE10125 7 5
1. Explain the concept of a prefix sum array and its applications
Prefix Sum Array: A prefix sum array is an array where each element at index i
stores the sum of elements from the start of the original array up to index i. It
allows constant-time queries for the sum of any subarray.
Applications:
• Range sum queries
• Subarray sum problems
• Equilibrium index
• Histogram water trapping
• Optimization in dynamic programming
2. Range Sum Using Prefix Sum Array
Algorithm:
1. Construct a prefix sum array.
2. To find the sum in range [L, R], use: prefix[R] - prefix[L-1].
java
CopyEdit
import java.util.*;
public class RangeSumPrefix {
public static void main(String[] args) {
int[] arr = {2, 4, 6, 8, 10};
int L = 1, R = 3;
int[] prefix = new int[arr.length];
prefix[0] = arr[0];
for (int i = 1; i < arr.length; i++) {
prefix[i] = prefix[i - 1] + arr[i];
}
int sum = L == 0 ? prefix[R] : prefix[R] - prefix[L - 1];
System.out.println(sum);
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Example:
Array: [2, 4, 6, 8, 10], Query: [1, 3] → Sum: 4 + 6 + 8 = 18
3. Equilibrium Index
Algorithm:
1. Compute total sum.
2. Iterate and track left sum.
3. If left sum == total - left - current, return index.
java
CopyEdit
public class EquilibriumIndex {
public static void main(String[] args) {
int[] arr = {-7, 1, 5, 2, -4, 3, 0};
int total = 0;
for (int num : arr) total += num;
int leftSum = 0;
for (int i = 0; i < arr.length; i++) {
if (leftSum == total - leftSum - arr[i]) {
System.out.println(i);
return;
}
leftSum += arr[i];
}
System.out.println(-1);
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: [-7, 1, 5, 2, -4, 3, 0] → Output: 3
4. Check if Prefix Sum == Suffix Sum
Algorithm:
1. Get total sum.
2. Iterate and compare left sum with right.
java
CopyEdit
public class EqualPrefixSuffix {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 3};
int total = 0, leftSum = 0;
for (int num : arr) total += num;
for (int i = 0; i < arr.length - 1; i++) {
leftSum += arr[i];
if (leftSum == total - leftSum) {
System.out.println(true);
return;
}
}
System.out.println(false);
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: [1, 2, 3, 3] → Output: true
5. Maximum Sum of Subarray of Size K
Algorithm:
1. Use sliding window of size k.
2. Track max sum by sliding the window.
java
CopyEdit
public class MaxSumSubarrayK {
public static void main(String[] args) {
int[] arr = {2, 1, 5, 1, 3, 2};
int k = 3;
int windowSum = 0;
for (int i = 0; i < k; i++) windowSum += arr[i];
int maxSum = windowSum;
for (int i = k; i < arr.length; i++) {
windowSum += arr[i] - arr[i - k];
maxSum = Math.max(maxSum, windowSum);
}
System.out.println(maxSum);
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Array: [2, 1, 5, 1, 3, 2], k = 3 → Max Sum: 9
6. Length of Longest Substring Without Repeating Characters
Algorithm:
1. Use a sliding window and HashSet.
2. Expand window with right pointer.
3. Remove from left until unique.
java
CopyEdit
import java.util.*;
public class LongestUniqueSubstring {
public static void main(String[] args) {
String s = "abcabcbb";
Set<Character> set = new HashSet<>();
int left = 0, maxLen = 0;
for (int right = 0; right < s.length(); right++) {
while (set.contains(s.charAt(right))) {
set.remove(s.charAt(left++));
}
set.add(s.charAt(right));
maxLen = Math.max(maxLen, right - left + 1);
}
System.out.println(maxLen);
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Example:
Input: "abcabcbb" → Output: 3
7. Explain the sliding window technique and its use in string problems
Sliding Window Technique:
A method where a subset of data (window) is moved over the input structure
(array/string) to track or compute specific values efficiently.
Applications in String Problems:
• Longest substring without repeating characters
• Minimum window substring
• Anagram checking
• Counting occurrences of pattern
Advantages:
• Reduces time complexity from O(n²) to O(n)
• No need for nested loops
• Efficient memory usage
8. Longest Palindromic Substring
Algorithm:
1. Expand from each center.
2. Track max length.
java
CopyEdit
public class LongestPalindrome {
public static void main(String[] args) {
String s = "babad";
int start = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expand(s, i, i);
int len2 = expand(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - start) {
start = i - (len - 1) / 2;
end = i + len / 2;
}
}
System.out.println(s.substring(start, end + 1));
}
static int expand(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
return right - left - 1;
}
}
Time Complexity: O(n²)
Space Complexity: O(1)
Example:
Input: "babad" → Output: "bab" or "aba"
9. Longest Common Prefix Among Strings
Algorithm:
1. Compare characters of the first string with others.
2. Stop when mismatch found.
java
CopyEdit
public class LongestCommonPrefix {
public static void main(String[] args) {
String[] strs = {"flower", "flow", "flight"};
if (strs.length == 0) {
System.out.println("");
return;
}
String prefix = strs[0];
for (int i = 1; i < strs.length; i++) {
while (strs[i].indexOf(prefix) != 0) {
prefix = prefix.substring(0, prefix.length() - 1);
}
}
System.out.println(prefix);
}
}
Time Complexity: O(n * m)
Space Complexity: O(1)
Example:
Input: ["flower","flow","flight"] → Output: "fl"
10. Generate All Permutations of a String
Algorithm:
1. Use backtracking.
2. Swap characters and recurse.
java
CopyEdit
public class PermutationsString {
public static void main(String[] args) {
String s = "abc";
permute(s.toCharArray(), 0);
}
static void permute(char[] s, int l) {
if (l == s.length - 1) {
System.out.println(new String(s));
return;
}
for (int i = l; i < s.length; i++) {
swap(s, i, l);
permute(s, l + 1);
swap(s, i, l);
}
}
static void swap(char[] s, int i, int j) {
char temp = s[i];
s[i] = s[j];
s[j] = temp;
}
}
Time Complexity: O(n!)
Space Complexity: O(n)
Example:
Input: "abc" → Output: abc, acb, bac, bca, cab, cba
11. Two Numbers in Sorted Array That Add to Target
Algorithm:
1. Use two pointers from start and end.
2. Move inward based on sum comparison.
java
CopyEdit
public class TwoSumSorted {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 6};
int target = 6;
int left = 0, right = arr.length - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) {
System.out.println(arr[left] + " " + arr[right]);
return;
} else if (sum < target) {
left++;
} else {
right--;
}
}
System.out.println("No pair found");
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: [1,2,3,4,6], Target = 6 → Output: 2 4
12. Lexicographically Next Greater Permutation
Algorithm:
1. Find decreasing suffix.
2. Swap with next larger number.
3. Reverse the suffix.
java
CopyEdit
import java.util.*;
public class NextPermutation {
public static void main(String[] args) {
int[] nums = {1, 2, 3};
int i = nums.length - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) i--;
if (i >= 0) {
int j = nums.length - 1;
while (nums[j] <= nums[i]) j--;
swap(nums, i, j);
}
reverse(nums, i + 1);
System.out.println(Arrays.toString(nums));
}
static void swap(int[] a, int i, int j) {
int temp = a[i];
a[i] = a[j];
a[j] = temp;
}
static void reverse(int[] a, int start) {
int end = a.length - 1;
while (start < end) swap(a, start++, end--);
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: [1,2,3] → Output: [1,3,2]
13. Merge Two Sorted Linked Lists
Algorithm:
1. Use dummy node and compare node values.
2. Attach smaller node to current pointer.
java
CopyEdit
public class MergeSortedLists {
static class Node {
int val;
Node next;
Node(int val) { this.val = val; }
}
public static void main(String[] args) {
Node l1 = new Node(1);
l1.next = new Node(3);
l1.next.next = new Node(5);
Node l2 = new Node(2);
l2.next = new Node(4);
l2.next.next = new Node(6);
Node head = merge(l1, l2);
while (head != null) {
System.out.print(head.val + " ");
head = head.next;
}
}
static Node merge(Node l1, Node l2) {
Node dummy = new Node(0);
Node current = dummy;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
current.next = l1;
l1 = l1.next;
} else {
current.next = l2;
l2 = l2.next;
}
current = current.next;
}
current.next = l1 != null ? l1 : l2;
return dummy.next;
}
}
Time Complexity: O(n + m)
Space Complexity: O(1)
Example:
Lists: 1→3→5, 2→4→6 → Output: 1→2→3→4→5→6
14. Median of Two Sorted Arrays Using Binary Search
Algorithm:
1. Binary search on the smaller array.
2. Partition both arrays at midpoints.
3. Use max of lefts and min of rights.
java
CopyEdit
public class MedianSortedArrays {
public static void main(String[] args) {
int[] A = {1, 3};
int[] B = {2};
if (A.length > B.length) {
int[] temp = A; A = B; B = temp;
}
int m = A.length, n = B.length;
int low = 0, high = m;
while (low <= high) {
int i = (low + high) / 2;
int j = (m + n + 1) / 2 - i;
int maxLeftA = (i == 0) ? Integer.MIN_VALUE : A[i - 1];
int minRightA = (i == m) ? Integer.MAX_VALUE : A[i];
int maxLeftB = (j == 0) ? Integer.MIN_VALUE : B[j - 1];
int minRightB = (j == n) ? Integer.MAX_VALUE : B[j];
if (maxLeftA <= minRightB && maxLeftB <= minRightA) {
if ((m + n) % 2 == 0)
System.out.println((Math.max(maxLeftA, maxLeftB) +
Math.min(minRightA, minRightB)) / 2.0);
else
System.out.println(Math.max(maxLeftA, maxLeftB));
return;
} else if (maxLeftA > minRightB) {
high = i - 1;
} else {
low = i + 1;
}
}
}
}
Time Complexity: O(log(min(m, n)))
Space Complexity: O(1)
Example:
Input: [1,3], [2] → Output: 2.0
15. k-th Smallest Element in a Sorted Matrix
Algorithm:
1. Use min heap with elements from the first column.
2. Push next elements in row for each pop.
java
CopyEdit
import java.util.*;
public class KthSmallestMatrix {
public static void main(String[] args) {
int[][] matrix = {
{1, 5, 9},
{10, 11, 13},
{12, 13, 15}
};
int k = 8;
PriorityQueue<int[]> minHeap = new
PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
int n = matrix.length;
for (int i = 0; i < n; i++) minHeap.offer(new int[]{matrix[i][0], i, 0});
for (int i = 0; i < k - 1; i++) {
int[] curr = minHeap.poll();
if (curr[2] < n - 1)
minHeap.offer(new int[]{matrix[curr[1]][curr[2] + 1], curr[1], curr[2] +
1});
}
System.out.println(minHeap.poll()[0]);
}
}
Time Complexity: O(k log n)
Space Complexity: O(n)
Example:
Input: k = 8 → Output: 13
16. Majority Element Appearing More Than n/2 Times
Algorithm:
1. Use Boyer-Moore Voting Algorithm.
java
CopyEdit
public class MajorityElement {
public static void main(String[] args) {
int[] nums = {2, 2, 1, 1, 1, 2, 2};
int count = 0, candidate = 0;
for (int num : nums) {
if (count == 0) candidate = num;
count += (num == candidate) ? 1 : -1;
}
System.out.println(candidate);
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: [2,2,1,1,1,2,2] → Output: 2
17. Trapping Rain Water Between Bars
Algorithm:
1. Precompute maxLeft and maxRight.
2. Water = min(maxLeft, maxRight) - height[i].
java
CopyEdit
public class TrappingRainWater {
public static void main(String[] args) {
int[] height = {0,1,0,2,1,0,1,3,2,1,2,1};
int n = height.length;
int[] left = new int[n];
int[] right = new int[n];
left[0] = height[0];
for (int i = 1; i < n; i++) left[i] = Math.max(left[i - 1], height[i]);
right[n - 1] = height[n - 1];
for (int i = n - 2; i >= 0; i--) right[i] = Math.max(right[i + 1], height[i]);
int water = 0;
for (int i = 0; i < n; i++) water += Math.min(left[i], right[i]) - height[i];
System.out.println(water);
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1] → Output: 6
18. Maximum XOR of Two Numbers in Array
Algorithm:
1. Use Trie or greedy bitwise method.
java
CopyEdit
import java.util.*;
public class MaxXOR {
public static void main(String[] args) {
int[] nums = {3, 10, 5, 25, 2, 8};
int max = 0, mask = 0;
for (int i = 31; i >= 0; i--) {
mask |= (1 << i);
Set<Integer> set = new HashSet<>();
for (int num : nums) set.add(num & mask);
int temp = max | (1 << i);
for (int prefix : set) {
if (set.contains(prefix ^ temp)) {
max = temp;
break;
}
}
}
System.out.println(max);
}
}
Time Complexity: O(n * 32)
Space Complexity: O(n)
Example:
Input: [3,10,5,25,2,8] → Output: 28
19. Maximum Product Subarray
Algorithm:
1. Track max and min at each index.
2. Update global max.
java
CopyEdit
public class MaxProductSubarray {
public static void main(String[] args) {
int[] nums = {2, 3, -2, 4};
int maxProd = nums[0], minProd = nums[0], result = nums[0];
for (int i = 1; i < nums.length; i++) {
int temp = maxProd;
maxProd = Math.max(nums[i], Math.max(maxProd * nums[i], minProd *
nums[i]));
minProd = Math.min(nums[i], Math.min(temp * nums[i], minProd *
nums[i]));
result = Math.max(result, maxProd);
}
System.out.println(result);
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: [2,3,-2,4] → Output: 6
20. Count Numbers with Unique Digits
Algorithm:
1. Use permutations.
2. Sum valid counts from 1 to n digits.
java
CopyEdit
public class UniqueDigitCount {
public static void main(String[] args) {
int n = 2;
if (n == 0) {
System.out.println(1);
return;
}
int result = 10, unique = 9, available = 9;
for (int i = 2; i <= n && available > 0; i++) {
unique *= available--;
result += unique;
}
System.out.println(result);
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: 2 → Output: 91
21. Count 1s in Binary Representation from 0 to n
Algorithm:
1. Use dynamic programming.
2. For each number, count 1s as res[i] = res[i >> 1] + (i & 1).
java
CopyEdit
import java.util.Arrays;
public class CountBits {
public static void main(String[] args) {
int n = 5;
int[] res = new int[n + 1];
for (int i = 1; i <= n; i++) {
res[i] = res[i >> 1] + (i & 1);
}
System.out.println(Arrays.toString(res));
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Example:
Input: 5 → Output: [0, 1, 1, 2, 1, 2]
22. Check if Number is Power of Two Using Bit Manipulation
Algorithm:
1. Power of two has only one set bit.
2. (n & (n - 1)) == 0
java
CopyEdit
public class PowerOfTwo {
public static void main(String[] args) {
int n = 16;
boolean isPower = n > 0 && (n & (n - 1)) == 0;
System.out.println(isPower);
}
}
Time Complexity: O(1)
Space Complexity: O(1)
Example:
Input: 16 → Output: true
23. Maximum XOR of Two Numbers in Array
(Same as Q18 — repeated, skipping code reuse per your condition.)
java
CopyEdit
import java.util.*;
public class MaxXORAgain {
public static void main(String[] args) {
int[] nums = {3, 10, 5, 25, 2, 8};
int max = 0, mask = 0;
for (int i = 31; i >= 0; i--) {
mask |= (1 << i);
Set<Integer> set = new HashSet<>();
for (int num : nums) set.add(num & mask);
int temp = max | (1 << i);
for (int prefix : set) {
if (set.contains(prefix ^ temp)) {
max = temp;
break;
}
}
}
System.out.println(max);
}
}
Time Complexity: O(n * 32)
Space Complexity: O(n)
24. Bit Manipulation and Its Advantages in Algorithm Design
Explanation: Bit manipulation involves operations directly on bits using
operators like AND (&), OR (|), XOR (^), NOT (~), left shift (<<), and right shift
(>>). These operations are extremely fast and efficient for performing low-level
arithmetic, checking even/odd, toggling bits, and optimizing space.
Advantages:
• Performance: Operations are done in constant time.
• Space Efficiency: Can pack multiple values into a single variable (e.g.,
bitmasking).
• Problem Solving: Useful in problems involving subsets, counting bits,
optimization with constraints on numbers.
25. Next Greater Element for Each Element in an Array
Algorithm:
1. Use stack to keep track of indices.
2. Traverse array from right to left.
java
CopyEdit
import java.util.*;
public class NextGreaterElement {
public static void main(String[] args) {
int[] nums = {4, 5, 2, 10, 8};
int[] res = new int[nums.length];
Stack<Integer> stack = new Stack<>();
for (int i = nums.length - 1; i >= 0; i--) {
while (!stack.isEmpty() && stack.peek() <= nums[i]) stack.pop();
res[i] = stack.isEmpty() ? -1 : stack.peek();
stack.push(nums[i]);
}
System.out.println(Arrays.toString(res));
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Example:
Input: [4,5,2,10,8] → Output: [5,10,10,-1,-1]
26. Remove n-th Node from End of Singly Linked List
Algorithm:
1. Use two-pointer approach.
2. Move first pointer n steps ahead.
3. Move both pointers until first reaches the end.
4. Remove the target node.
java
CopyEdit
public class RemoveNthFromEnd {
static class Node {
int val;
Node next;
Node(int val) { this.val = val; }
}
public static void main(String[] args) {
Node head = new Node(1);
head.next = new Node(2);
head.next.next = new Node(3);
head.next.next.next = new Node(4);
head.next.next.next.next = new Node(5);
int n = 2;
head = removeNthFromEnd(head, n);
while (head != null) {
System.out.print(head.val + " ");
head = head.next;
}
}
static Node removeNthFromEnd(Node head, int n) {
Node dummy = new Node(0);
dummy.next = head;
Node first = dummy, second = dummy;
for (int i = 0; i <= n; i++) first = first.next;
while (first != null) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return dummy.next;
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: 1→2→3→4→5, n = 2 → Output: 1→2→3→5
27. Find Node Where Two Singly Linked Lists Intersect
Algorithm:
1. Compute lengths of both lists.
2. Align heads by skipping extra nodes.
3. Traverse both lists together to find intersection.
java
CopyEdit
public class IntersectionLinkedList {
static class Node {
int val;
Node next;
Node(int val) { this.val = val; }
}
public static void main(String[] args) {
Node a = new Node(1);
a.next = new Node(2);
Node b = new Node(3);
b.next = a.next;
a.next.next = new Node(4);
a.next.next.next = new Node(5);
Node intersection = findIntersection(a, b);
System.out.println(intersection != null ? intersection.val : "No
Intersection");
}
static Node findIntersection(Node a, Node b) {
Node p1 = a, p2 = b;
while (p1 != p2) {
p1 = (p1 == null) ? b : p1.next;
p2 = (p2 == null) ? a : p2.next;
}
return p1;
}
}
Time Complexity: O(n + m)
Space Complexity: O(1)
Example:
Input: 1→2→4→5 and 3→2→4→5 → Output: 2
28. Implement Two Stacks in One Array
Algorithm:
1. Use two indices, one from the left, one from the right.
2. Push to respective ends and adjust indices.
java
CopyEdit
public class TwoStacks {
static class TwoStack {
int[] arr;
int top1, top2, size;
TwoStack(int n) {
size = n;
arr = new int[n];
top1 = -1;
top2 = n;
}
void push1(int x) {
if (top1 < top2 - 1) arr[++top1] = x;
}
void push2(int x) {
if (top1 < top2 - 1) arr[--top2] = x;
}
int pop1() { return (top1 >= 0) ? arr[top1--] : -1; }
int pop2() { return (top2 < size) ? arr[top2++] : -1; }
}
public static void main(String[] args) {
TwoStack ts = new TwoStack(5);
ts.push1(10);
ts.push2(20);
ts.push1(30);
System.out.println(ts.pop1());
System.out.println(ts.pop2());
}
}
Time Complexity: O(1)
Space Complexity: O(n)
Example:
Input: push1(10), push2(20), push1(30), pop1(), pop2() → Output: 30 20
29. Check if Integer is Palindrome Without String Conversion
Algorithm:
1. Reverse half of the number.
2. Compare reversed half with original.
java
CopyEdit
public class PalindromeNumber {
public static void main(String[] args) {
int x = 121;
if (x < 0 || (x % 10 == 0 && x != 0)) {
System.out.println(false);
return;
}
int rev = 0;
while (x > rev) {
rev = rev * 10 + x % 10;
x /= 10;
}
System.out.println(x == rev || x == rev / 10);
}
}
Time Complexity: O(log n)
Space Complexity: O(1)
Example:
Input: 121 → Output: true
30. Concept of Linked Lists and Applications in Algorithm Design
Explanation: A linked list is a dynamic data structure where elements (nodes)
are linked using pointers.
Types:
• Singly Linked List: Each node has a value and a pointer to the next node.
• Doubly Linked List: Each node has pointers to both previous and next
nodes.
• Circular Linked List: The last node points back to the first node.
Applications:
• Dynamic Memory Allocation: No need for a fixed size like arrays.
• Efficient Insertions/Deletions: O(1) complexity at head or tail.
• Implementing Stacks & Queues: Used in real-time data structures.
• Graph Representation: Adjacency list representation.
• Hash Tables: Used for separate chaining in collision handling.
31. Maximum in Every Sliding Window of Size K Using Deque
Algorithm:
1. Use deque to store indices.
2. Maintain decreasing order in deque.
java
CopyEdit
import java.util.*;
public class SlidingWindowMax {
public static void main(String[] args) {
int[] nums = {1, 3, -1, -3, 5, 3, 6, 7};
int k = 3;
int n = nums.length;
int[] res = new int[n - k + 1];
Deque<Integer> dq = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
while (!dq.isEmpty() && dq.peek() < i - k + 1) dq.poll();
while (!dq.isEmpty() && nums[dq.peekLast()] < nums[i]) dq.pollLast();
dq.offer(i);
if (i >= k - 1) res[i - k + 1] = nums[dq.peek()];
}
System.out.println(Arrays.toString(res));
}
}
Time Complexity: O(n)
Space Complexity: O(k)
Example:
Input: nums = [1,3,-1,-3,5,3,6,7], k = 3 → Output: [3,3,5,5,6,7]
32. Largest Rectangle in Histogram
Algorithm:
1. Use stack to maintain bars.
2. Calculate area when current bar is smaller.
java
CopyEdit
import java.util.*;
public class LargestRectangle {
public static void main(String[] args) {
int[] heights = {2,1,5,6,2,3};
Stack<Integer> stack = new Stack<>();
int maxArea = 0;
int n = heights.length;
for (int i = 0; i <= n; i++) {
int h = (i == n) ? 0 : heights[i];
while (!stack.isEmpty() && h < heights[stack.peek()]) {
int height = heights[stack.pop()];
int width = stack.isEmpty() ? i : i - stack.peek() - 1;
maxArea = Math.max(maxArea, height * width);
}
stack.push(i);
}
System.out.println(maxArea);
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Example:
Input: [2,1,5,6,2,3] → Output: 10
33. Sliding Window Technique and Its Applications in Array Problems
Explanation: The sliding window is a method for optimizing brute-force
algorithms in array or string problems.
Concept: Use two pointers to create a window which moves through the data
to track sums, counts, or other properties.
Common Applications:
• Maximum/minimum in a subarray.
• Longest substring with unique characters.
• Subarrays with sum equal to K.
• Fixed-size window operations.
Benefits:
• Reduces time complexity from O(n²) to O(n).
• Requires minimal extra space.
34. Subarray Sum Equals K Using Hashing
Algorithm:
1. Use HashMap to store cumulative sums.
2. Count matching previous prefix sums.
java
CopyEdit
import java.util.*;
public class SubarraySumEqualsK {
public static void main(String[] args) {
int[] nums = {1, 1, 1};
int k = 2;
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
int sum = 0, count = 0;
for (int num : nums) {
sum += num;
count += map.getOrDefault(sum - k, 0);
map.put(sum, map.getOrDefault(sum, 0) + 1);
}
System.out.println(count);
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Example:
Input: nums = [1,1,1], k = 2 → Output: 2
35. K Most Frequent Elements Using Priority Queue
Algorithm:
1. Count frequencies using HashMap.
2. Use Min-Heap of size k to track top elements.
java
CopyEdit
import java.util.*;
public class TopKFrequent {
public static void main(String[] args) {
int[] nums = {1,1,1,2,2,3};
int k = 2;
Map<Integer, Integer> freq = new HashMap<>();
for (int num : nums) freq.put(num, freq.getOrDefault(num, 0) + 1);
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> freq.get(a) -
freq.get(b));
for (int key : freq.keySet()) {
pq.offer(key);
if (pq.size() > k) pq.poll();
}
int[] res = new int[k];
for (int i = k - 1; i >= 0; i--) res[i] = pq.poll();
System.out.println(Arrays.toString(res));
}
}
Time Complexity: O(n log k)
Space Complexity: O(n)
Example:
Input: [1,1,1,2,2,3], k=2 → Output: [1,2]
36. Generate All Subsets of a Given Array
Algorithm:
1. Use backtracking to explore all possibilities.
2. Add current subset to result.
java
CopyEdit
import java.util.*;
public class Subsets {
public static void main(String[] args) {
int[] nums = {1, 2, 3};
List<List<Integer>> res = new ArrayList<>();
backtrack(res, new ArrayList<>(), nums, 0);
System.out.println(res);
}
static void backtrack(List<List<Integer>> res, List<Integer> temp, int[] nums,
int start) {
res.add(new ArrayList<>(temp));
for (int i = start; i < nums.length; i++) {
temp.add(nums[i]);
backtrack(res, temp, nums, i + 1);
temp.remove(temp.size() - 1);
}
}
}
Time Complexity: O(2ⁿ)
Space Complexity: O(n)
Example:
Input: [1, 2, 3] → Output: [[],[1],[1,2],[1,2,3],[1,3],[2],[2,3],[3]]
37. Find All Unique Combinations That Sum to Target
Algorithm:
1. Use backtracking.
2. Include current number multiple times if needed.
java
CopyEdit
import java.util.*;
public class CombinationSum {
public static void main(String[] args) {
int[] candidates = {2,3,6,7};
int target = 7;
List<List<Integer>> res = new ArrayList<>();
backtrack(res, new ArrayList<>(), candidates, target, 0);
System.out.println(res);
}
static void backtrack(List<List<Integer>> res, List<Integer> temp, int[] nums,
int remain, int start) {
if (remain == 0) {
res.add(new ArrayList<>(temp));
return;
}
for (int i = start; i < nums.length; i++) {
if (nums[i] <= remain) {
temp.add(nums[i]);
backtrack(res, temp, nums, remain - nums[i], i);
temp.remove(temp.size() - 1);
}
}
}
}
Time Complexity: O(2ⁿ)
Space Complexity: O(n)
Example:
Input: [2,3,6,7], target = 7 → Output: [[2,2,3],[7]]
38. Generate All Permutations of a Given Array
Algorithm:
1. Use backtracking.
2. Swap elements to generate permutations.
java
CopyEdit
import java.util.*;
public class Permutations {
public static void main(String[] args) {
int[] nums = {1, 2, 3};
List<List<Integer>> res = new ArrayList<>();
backtrack(res, nums, 0);
System.out.println(res);
}
static void backtrack(List<List<Integer>> res, int[] nums, int start) {
if (start == nums.length) {
List<Integer> list = new ArrayList<>();
for (int num : nums) list.add(num);
res.add(list);
return;
}
for (int i = start; i < nums.length; i++) {
swap(nums, start, i);
backtrack(res, nums, start + 1);
swap(nums, start, i);
}
}
static void swap(int[] nums, int i, int j) {
int t = nums[i]; nums[i] = nums[j]; nums[j] = t;
}
}
Time Complexity: O(n!)
Space Complexity: O(n)
Example:
Input: [1,2,3] → Output: All permutations
39. Difference Between Subsets and Permutations
Explanation:
Subsets:
• Contain 0 to n elements in original order.
• Order doesn't matter.
• Total: 2ⁿ subsets.
Example: {1,2} → [[], [1], [2], [1,2]]
Permutations:
• Contain all elements with different orderings.
• Order matters.
• Total: n! permutations.
Example: {1,2} → [[1,2], [2,1]]
Key Differences:
• Count: Subsets → 2ⁿ, Permutations → n!
• Order Sensitivity: Not in subsets, required in permutations.
40. Find Element with Maximum Frequency in an Array
Algorithm:
1. Count frequency using HashMap.
2. Track max frequency element.
java
CopyEdit
import java.util.*;
public class MaxFrequencyElement {
public static void main(String[] args) {
int[] nums = {1, 3, 2, 1, 4, 1};
Map<Integer, Integer> map = new HashMap<>();
int maxFreq = 0, result = nums[0];
for (int num : nums) {
int freq = map.getOrDefault(num, 0) + 1;
map.put(num, freq);
if (freq > maxFreq) {
maxFreq = freq;
result = num;
}
}
System.out.println(result);
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Example:
Input: [1,3,2,1,4,1] → Output: 1
41. Maximum Subarray Sum Using Kadane’s Algorithm
java
CopyEdit
public class MaxSubarrayKadane {
public static void main(String[] args) {
int[] nums = {-2,1,-3,4,-1,2,1,-5,4};
int maxSum = nums[0], currSum = nums[0];
for (int i = 1; i < nums.length; i++) {
currSum = Math.max(nums[i], currSum + nums[i]);
maxSum = Math.max(maxSum, currSum);
}
System.out.println(maxSum);
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: [-2,1,-3,4,-1,2,1,-5,4] → Output: 6
42. Concept of Dynamic Programming and Its Use in Solving the Maximum
Subarray Problem
Explanation:
Dynamic Programming (DP):
• A method to solve problems by breaking them into overlapping
subproblems and storing the results.
Use in Maximum Subarray:
• Use a DP array dp[i] = max subarray sum ending at index i.
• Recurrence: dp[i] = max(arr[i], dp[i-1] + arr[i])
Optimized Version (Kadane’s Algorithm):
• Uses only variables instead of arrays.
• Tracks current and global maximum sum.
Advantages:
• Reduces time from O(n²) to O(n)
• Efficient space with constant usage
43. Top K Frequent Elements in an Array
java
CopyEdit
import java.util.*;
public class TopKFrequentElements {
public static void main(String[] args) {
int[] nums = {1,1,1,2,2,3};
int k = 2;
Map<Integer, Integer> count = new HashMap<>();
for (int num : nums) count.put(num, count.getOrDefault(num, 0) + 1);
PriorityQueue<Integer> pq = new PriorityQueue<>((a, b) -> count.get(a) -
count.get(b));
for (int num : count.keySet()) {
pq.offer(num);
if (pq.size() > k) pq.poll();
}
int[] res = new int[k];
for (int i = k - 1; i >= 0; i--) res[i] = pq.poll();
System.out.println(Arrays.toString(res));
}
}
Time Complexity: O(n log k)
Space Complexity: O(n)
Example:
Input: [1,1,1,2,2,3], k=2 → Output: [1,2]
44. Two Numbers Add to Target Using Hashing
java
CopyEdit
import java.util.*;
public class TwoSumHashing {
public static void main(String[] args) {
int[] nums = {2,7,11,15};
int target = 9;
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int comp = target - nums[i];
if (map.containsKey(comp)) {
System.out.println(Arrays.toString(new int[]{map.get(comp), i}));
return;
}
map.put(nums[i], i);
}
}
}
Time Complexity: O(n)
Space Complexity: O(n)
Example:
Input: [2,7,11,15], target=9 → Output: [0,1]
45. Concept of Priority Queues and Their Applications in Algorithm Design
Explanation:
Priority Queue:
• A special type of queue where each element has a priority.
• Elements are served based on priority, not just insertion order.
Implementation:
• Java uses PriorityQueue which is a Min-Heap by default.
Applications:
• Dijkstra’s shortest path algorithm
• Top K elements (frequent/largest/smallest)
• Huffman encoding
• Real-time scheduling systems
Advantages:
• Efficient insert and delete (O(log n))
46. Longest Palindromic Substring in a Given String
java
CopyEdit
public class LongestPalindrome {
public static void main(String[] args) {
String s = "babad";
int start = 0, maxLen = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expand(s, i, i);
int len2 = expand(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > maxLen) {
start = i - (len - 1) / 2;
maxLen = len;
}
}
System.out.println(s.substring(start, start + maxLen));
}
static int expand(String s, int left, int right) {
while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right))
{
left--; right++;
}
return right - left - 1;
}
}
Time Complexity: O(n²)
Space Complexity: O(1)
Example:
Input: "babad" → Output: "bab" or "aba"
47. Concept of Histogram Problems and Their Applications
Explanation:
Histogram Problems:
• Typically involve arrays of heights representing bars.
Key Applications:
• Largest rectangle in histogram
• Trapping rain water
• Skyline problem
Use in Algorithms:
• Monotonic stack for efficient area/space calculations
• Sliding window or two pointers
Real-world Usage:
• Data visualization optimization
• Memory management
• Image processing (histogram equalization)
48. Next Permutation of a Given Array
java
CopyEdit
import java.util.*;
public class NextPermutation {
public static void main(String[] args) {
int[] nums = {1,2,3};
int i = nums.length - 2;
while (i >= 0 && nums[i] >= nums[i + 1]) i--;
if (i >= 0) {
int j = nums.length - 1;
while (nums[j] <= nums[i]) j--;
swap(nums, i, j);
}
reverse(nums, i + 1);
System.out.println(Arrays.toString(nums));
}
static void swap(int[] nums, int i, int j) {
int t = nums[i]; nums[i] = nums[j]; nums[j] = t;
}
static void reverse(int[] nums, int start) {
int i = start, j = nums.length - 1;
while (i < j) swap(nums, i++, j--);
}
}
Time Complexity: O(n)
Space Complexity: O(1)
Example:
Input: [1,2,3] → Output: [1,3,2]
49. Intersection of Two Linked Lists
java
CopyEdit
public class LinkedListIntersection {
static class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public static void main(String[] args) {
// Example nodes creation skipped; assume intersectNode is shared
}
static ListNode getIntersectionNode(ListNode a, ListNode b) {
ListNode p1 = a, p2 = b;
while (p1 != p2) {
p1 = (p1 == null) ? b : p1.next;
p2 = (p2 == null) ? a : p2.next;
}
return p1;
}
}
Time Complexity: O(n + m)
Space Complexity: O(1)
50. Concept of Equilibrium Index and Its Applications
Explanation:
Equilibrium Index:
• An index i such that the sum of elements before i is equal to the sum
after i.
Applications:
• Load balancing in distributed systems
• Financial models (equal inflow/outflow)
• Sensor-based data where equilibrium is needed
Approach:
• Total sum, then subtract left sums as we traverse to check equilibrium