Top 150 DSA Interview Questions
Part 1: Arrays & Strings — Complete Java Solutions
BossCoder Academy | Questions 1 – 40
Each solution includes: Problem approach, Clean Java code, Time & Space complexity.
01 — ARRAYS (Q1 – Q20)
Q1. Two Sum
Approach: Use a HashMap to store each element's value→index. For every element, check if (target - element)
exists in the map.
import [Link]; class Solution { public int[] twoSum(int[] nums, int target) {
HashMap<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < [Link]; i++) { int
complement = target - nums[i]; if ([Link](complement)) return new
int[]{[Link](complement), i}; [Link](nums[i], i); } return new int[]{}; } }
Time: O(n) Space: O(n)
Q2. Best Time to Buy and Sell Stock
Approach: Track the minimum price seen so far. At each day, compute profit = price - minPrice and update
maxProfit.
class Solution { public int maxProfit(int[] prices) { int minPrice = Integer.MAX_VALUE; int
maxProfit = 0; for (int price : prices) { if (price < minPrice) minPrice = price; else if (price -
minPrice > maxProfit) maxProfit = price - minPrice; } return maxProfit; } }
Time: O(n) Space: O(1)
Q3. Product of Array Except Self
Approach: Build a prefix product array (left pass) and multiply with suffix products (right pass) without using division.
class Solution { public int[] productExceptSelf(int[] nums) { int n = [Link]; int[] result =
new int[n]; result[0] = 1; // Left pass: result[i] = product of all elements to the left for (int i
= 1; i < n; i++) result[i] = result[i - 1] * nums[i - 1]; // Right pass: multiply with suffix
products int right = 1; for (int i = n - 1; i >= 0; i--) { result[i] *= right; right *= nums[i]; }
return result; } }
Time: O(n) Space: O(1) extra
Q4. Maximum Subarray (Kadane's Algorithm)
Approach: Keep a running sum. If adding the current element is worse than starting fresh, reset. Track global
maximum.
class Solution { public int maxSubArray(int[] nums) { int currentSum = nums[0]; int maxSum =
nums[0]; for (int i = 1; i < [Link]; i++) { currentSum = [Link](nums[i], currentSum +
nums[i]); maxSum = [Link](maxSum, currentSum); } return maxSum; } }
Time: O(n) Space: O(1)
Q5. Maximum Product Subarray
Approach: Track both max and min products ending at each index (min needed because negative*negative =
positive).
class Solution { public int maxProduct(int[] nums) { int maxProd = nums[0], minProd = nums[0],
result = nums[0]; for (int i = 1; i < [Link]; i++) { int temp = maxProd; maxProd =
[Link](nums[i], [Link](maxProd * nums[i], minProd * nums[i])); minProd = [Link](nums[i],
[Link](temp * nums[i], minProd * nums[i])); result = [Link](result, maxProd); } return result;
} }
Time: O(n) Space: O(1)
Q6. Search in Rotated Sorted Array
Approach: Modified binary search: determine which half is sorted, then decide which half the target lies in.
class Solution { public int search(int[] nums, int target) { int lo = 0, hi = [Link] - 1;
while (lo <= hi) { int mid = lo + (hi - lo) / 2; if (nums[mid] == target) return mid; // Left half
is sorted if (nums[lo] <= nums[mid]) { if (target >= nums[lo] && target < nums[mid]) hi = mid - 1;
else lo = mid + 1; } else { // Right half is sorted if (target > nums[mid] && target <= nums[hi])
lo = mid + 1; else hi = mid - 1; } } return -1; } }
Time: O(log n) Space: O(1)
Q7. 3 Sum
Approach: Sort array. For each element, use two-pointer technique on the remaining subarray to find pairs that sum
to zero.
import [Link].*; class Solution { public List<List<Integer>> threeSum(int[] nums) {
[Link](nums); List<List<Integer>> result = new ArrayList<>(); for (int i = 0; i < [Link]
- 2; i++) { if (i > 0 && nums[i] == nums[i - 1]) continue; // skip duplicates int lo = i + 1, hi =
[Link] - 1; while (lo < hi) { int sum = nums[i] + nums[lo] + nums[hi]; if (sum == 0) {
[Link]([Link](nums[i], nums[lo], nums[hi])); while (lo < hi && nums[lo] == nums[lo + 1])
lo++; while (lo < hi && nums[hi] == nums[hi - 1]) hi--; lo++; hi--; } else if (sum < 0) lo++; else
hi--; } } return result; } }
Time: O(n^2) Space: O(1) extra
Q8. Trapping Rain Water
Approach: Two-pointer approach: maintain leftMax and rightMax. Water at position = min(leftMax, rightMax) -
height[i].
class Solution { public int trap(int[] height) { int lo = 0, hi = [Link] - 1; int leftMax =
0, rightMax = 0, water = 0; while (lo < hi) { if (height[lo] < height[hi]) { if (height[lo] >=
leftMax) leftMax = height[lo]; else water += leftMax - height[lo]; lo++; } else { if (height[hi] >=
rightMax) rightMax = height[hi]; else water += rightMax - height[hi]; hi--; } } return water; } }
Time: O(n) Space: O(1)
Q9. Merge Intervals
Approach: Sort by start time. Iterate and merge overlapping intervals by comparing end of last merged with start of
current.
import [Link].*; class Solution { public int[][] merge(int[][] intervals) {
[Link](intervals, (a, b) -> a[0] - b[0]); List<int[]> merged = new ArrayList<>(); for (int[]
interval : intervals) { if ([Link]() || [Link]([Link]()-1)[1] < interval[0])
[Link](interval); else [Link]([Link]()-1)[1] =
[Link]([Link]([Link]()-1)[1], interval[1]); } return [Link](new
int[[Link]()][]); } }
Time: O(n log n) Space: O(n)
Q10. Container With Most Water
Approach: Two-pointer from both ends. Move the pointer with the shorter height inward; track max area at each step.
class Solution { public int maxArea(int[] height) { int lo = 0, hi = [Link] - 1, maxWater =
0; while (lo < hi) { int water = [Link](height[lo], height[hi]) * (hi - lo); maxWater =
[Link](maxWater, water); if (height[lo] < height[hi]) lo++; else hi--; } return maxWater; } }
Time: O(n) Space: O(1)
Q11. Rotate Array
Approach: Reverse the whole array, then reverse first k elements, then reverse the remaining n-k elements.
class Solution { public void rotate(int[] nums, int k) { int n = [Link]; k %= n; reverse(nums,
0, n - 1); reverse(nums, 0, k - 1); reverse(nums, k, n - 1); } private void reverse(int[] nums, int
lo, int hi) { while (lo < hi) { int tmp = nums[lo]; nums[lo] = nums[hi]; nums[hi] = tmp; lo++;
hi--; } } }
Time: O(n) Space: O(1)
Q12. Sort Colors (Dutch National Flag)
Approach: Three-pointer approach: low, mid, high. Place 0s at low, 2s at high, 1s stay in middle.
class Solution { public void sortColors(int[] nums) { int lo = 0, mid = 0, hi = [Link] - 1;
while (mid <= hi) { if (nums[mid] == 0) { int tmp = nums[lo]; nums[lo] = nums[mid]; nums[mid] =
tmp; lo++; mid++; } else if (nums[mid] == 1) { mid++; } else { int tmp = nums[mid]; nums[mid] =
nums[hi]; nums[hi] = tmp; hi--; } } } }
Time: O(n) Space: O(1)
Q13. Equilibrium Index
Approach: Compute total sum. Traverse array maintaining leftSum; equilibrium when leftSum == totalSum - leftSum -
nums[i].
class Solution { public int equilibriumIndex(int[] arr) { int total = 0; for (int x : arr) total +=
x; int leftSum = 0; for (int i = 0; i < [Link]; i++) { total -= arr[i]; if (leftSum == total)
return i; leftSum += arr[i]; } return -1; } }
Time: O(n) Space: O(1)
Q14. Kth Largest Element in an Array
Approach: Use a min-heap of size k. After processing all elements, the heap's root is the kth largest.
import [Link]; class Solution { public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> minHeap = new PriorityQueue<>(); for (int num : nums) { [Link](num);
if ([Link]() > k) [Link](); } return [Link](); } }
Time: O(n log k) Space: O(k)
Q15. Count Inversions
Approach: Modified merge sort: while merging, whenever a right element is placed before a left element, add
remaining left count.
class Solution { static long merge(int[] arr, int[] temp, int lo, int mid, int hi) { long count =
0; int i = lo, j = mid + 1, k = lo; while (i <= mid && j <= hi) { if (arr[i] <= arr[j]) temp[k++] =
arr[i++]; else { temp[k++] = arr[j++]; count += (mid - i + 1); } } while (i <= mid) temp[k++] =
arr[i++]; while (j <= hi) temp[k++] = arr[j++]; for (int x = lo; x <= hi; x++) arr[x] = temp[x];
return count; } static long mergeSort(int[] arr, int[] temp, int lo, int hi) { long count = 0; if
(lo < hi) { int mid = (lo + hi) / 2; count += mergeSort(arr, temp, lo, mid); count +=
mergeSort(arr, temp, mid + 1, hi); count += merge(arr, temp, lo, mid, hi); } return count; } public
long countInversions(int[] arr) { return mergeSort(arr, new int[[Link]], 0, [Link] - 1); }
}
Time: O(n log n) Space: O(n)
Q16. Maximum Sum Circular Subarray
Approach: Max circular subarray = max(normal Kadane result, totalSum - minSubarraySum). Handle all-negative
edge case.
class Solution { public int maxSubarraySumCircular(int[] nums) { int totalSum = 0, maxSum =
nums[0], curMax = 0; int minSum = nums[0], curMin = 0; for (int num : nums) { curMax =
[Link](curMax + num, num); maxSum = [Link](maxSum, curMax); curMin = [Link](curMin + num,
num); minSum = [Link](minSum, curMin); totalSum += num; } return maxSum > 0 ? [Link](maxSum,
totalSum - minSum) : maxSum; } }
Time: O(n) Space: O(1)
Q17. Merge Sorted Arrays Without Extra Space
Approach: Use gap method: start gap = ceil((m+n)/2), compare and swap elements at gap distance, halve gap each
iteration.
class Solution { public void merge(int[] arr1, int m, int[] arr2, int n) { // Place arr2 values
after arr1's m elements conceptually via gap method int[] a = new int[m + n]; for (int i = 0; i <
m; i++) a[i] = arr1[i]; for (int i = 0; i < n; i++) a[m + i] = arr2[i]; int gap = (m + n + 1) / 2;
while (gap > 0) { for (int i = 0; i + gap < m + n; i++) { if (a[i] > a[i + gap]) { int tmp = a[i];
a[i] = a[i + gap]; a[i + gap] = tmp; } } if (gap == 1) break; gap = (gap + 1) / 2; } for (int i = 0;
i < m; i++) arr1[i] = a[i]; for (int i = 0; i < n; i++) arr2[i] = a[m + i]; } }
Time: O((m+n) log(m+n)) Space: O(1)
Q18. Find Duplicates in Array
Approach: For each element, negate value at index nums[i]-1. If already negative, that index+1 is a duplicate.
import [Link].*; class Solution { public List<Integer> findDuplicates(int[] nums) {
List<Integer> result = new ArrayList<>(); for (int num : nums) { int idx = [Link](num) - 1; if
(nums[idx] < 0) [Link]([Link](num)); else nums[idx] = -nums[idx]; } return result; } }
Time: O(n) Space: O(1) extra
Q19. Wave Array
Approach: Sort array. Swap adjacent elements in pairs: swap arr[0] with arr[1], arr[2] with arr[3], etc.
import [Link]; class Solution { public void waveArray(int[] arr) { [Link](arr); for
(int i = 0; i + 1 < [Link]; i += 2) { int tmp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = tmp; }
} // O(1) approach: ensure arr[even] >= arr[odd neighbors] public void waveArrayO1(int[] arr) { for
(int i = 0; i < [Link]; i += 2) { if (i > 0 && arr[i - 1] > arr[i]) { int t = arr[i]; arr[i] =
arr[i-1]; arr[i-1] = t; } if (i + 1 < [Link] && arr[i + 1] > arr[i]) { int t = arr[i]; arr[i] =
arr[i+1]; arr[i+1] = t; } } } }
Time: O(n log n) / O(n) Space: O(1)
Q20. Alternate High Low Array
Approach: Sort array. Swap adjacent pairs — even-indexed elements become peaks, odd-indexed become valleys.
import [Link]; class Solution { public void alternateHighLow(int[] arr) {
[Link](arr); // After sorting, swap every pair: index 1&2, 3&4, ... for (int i = 1; i + 1 <
[Link]; i += 2) { int tmp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = tmp; } } }
Time: O(n log n) Space: O(1)
02 — STRINGS (Q21 – Q40)
Q21. Longest Substring Without Repeating Characters
Approach: Sliding window with a HashSet. Expand right, shrink left whenever a duplicate character is found.
import [Link]; class Solution { public int lengthOfLongestSubstring(String s) {
HashSet<Character> set = new HashSet<>(); int left = 0, maxLen = 0; for (int right = 0; right <
[Link](); right++) { while ([Link]([Link](right))) [Link]([Link](left++));
[Link]([Link](right)); maxLen = [Link](maxLen, right - left + 1); } return maxLen; } }
Time: O(n) Space: O(min(n, charset))
Q22. Group Anagrams
Approach: Sort each word to get a canonical key. Group all words sharing the same sorted key in a HashMap.
import [Link].*; class Solution { public List<List<String>> groupAnagrams(String[] strs) {
Map<String, List<String>> map = new HashMap<>(); for (String s : strs) { char[] arr =
[Link](); [Link](arr); String key = new String(arr); [Link](key, k -> new
ArrayList<>()).add(s); } return new ArrayList<>([Link]()); } }
Time: O(n * k log k) Space: O(n*k)
Q23. Longest Palindromic Substring
Approach: Expand around every center (both single char and between chars). Track the longest palindrome found.
class Solution { private int start = 0, maxLen = 1; public String longestPalindrome(String s) { if
([Link]() < 2) return s; for (int i = 0; i < [Link]() - 1; i++) { expand(s, i, i); //
odd-length expand(s, i, i + 1); // even-length } return [Link](start, start + maxLen); }
private void expand(String s, int lo, int hi) { while (lo >= 0 && hi < [Link]() && [Link](lo)
== [Link](hi)) { lo--; hi++; } if (hi - lo - 1 > maxLen) { maxLen = hi - lo - 1; start = lo + 1; }
} }
Time: O(n^2) Space: O(1)
Q24. Smallest Window Containing All Characters
Approach: Sliding window with two frequency maps. Shrink from left when all required characters are covered.
import [Link]; class Solution { public String smallestWindow(String s, String t) {
HashMap<Character, Integer> need = new HashMap<>(); for (char c : [Link]()) [Link](c, 1,
Integer::sum); int lo = 0, have = 0, required = [Link](); int minLen = Integer.MAX_VALUE,
minStart = 0; HashMap<Character, Integer> window = new HashMap<>(); for (int hi = 0; hi <
[Link](); hi++) { char c = [Link](hi); [Link](c, 1, Integer::sum); if
([Link](c) && [Link](c).equals([Link](c))) have++; while (have == required) { if
(hi - lo + 1 < minLen) { minLen = hi - lo + 1; minStart = lo; } char leftC = [Link](lo);
[Link](leftC, -1, Integer::sum); if ([Link](leftC) && [Link](leftC) <
[Link](leftC)) have--; lo++; } } return minLen == Integer.MAX_VALUE ? "" : [Link](minStart,
minStart + minLen); } }
Time: O(n + m) Space: O(n + m)
Q25. Check for Anagram
Approach: Count frequency of each character in both strings using an int[26] array. Compare the arrays.
class Solution { public boolean isAnagram(String s, String t) { if ([Link]() != [Link]())
return false; int[] count = new int[26]; for (char c : [Link]()) count[c - 'a']++; for (char
c : [Link]()) count[c - 'a']--; for (int x : count) if (x != 0) return false; return true; }
}
Time: O(n) Space: O(1)
Q26. Longest Common Prefix
Approach: Sort the array. Compare only the first and last strings character by character — their common prefix is the
answer.
class Solution { public String longestCommonPrefix(String[] strs) { if (strs == null || [Link]
== 0) return ""; [Link](strs); String first = strs[0], last = strs[[Link] - 1];
int i = 0; while (i < [Link]() && i < [Link]() && [Link](i) == [Link](i))
i++; return [Link](0, i); } }
Time: O(n log n * m) Space: O(1)
Q27. String to Integer (Atoi)
Approach: Skip whitespace, handle sign, read digits carefully. Clamp to Integer.MAX_VALUE / MIN_VALUE on
overflow.
class Solution { public int myAtoi(String s) { int i = 0, n = [Link](), sign = 1; long result =
0; while (i < n && [Link](i) == ' ') i++; if (i < n && ([Link](i) == '+' || [Link](i) ==
'-')) sign = ([Link](i++) == '+') ? 1 : -1; while (i < n && [Link]([Link](i))) {
result = result * 10 + ([Link](i++) - '0'); if (result * sign > Integer.MAX_VALUE) return
Integer.MAX_VALUE; if (result * sign < Integer.MIN_VALUE) return Integer.MIN_VALUE; } return
(int)(result * sign); } }
Time: O(n) Space: O(1)
Q28. Valid Palindrome
Approach: Two pointers from both ends. Skip non-alphanumeric characters and compare lowercased characters.
class Solution { public boolean isPalindrome(String s) { int lo = 0, hi = [Link]() - 1; while (lo
< hi) { while (lo < hi && )) lo++; while (lo < hi &&
)) hi--; if ([Link]([Link](lo)) !=
[Link]([Link](hi))) return false; lo++; hi--; } return true; } }
Time: O(n) Space: O(1)
Q29. Implement strStr() — Needle in Haystack
Approach: KMP (Knuth-Morris-Pratt): build LPS (failure function) array for needle, then scan haystack using it.
class Solution { public int strStr(String haystack, String needle) { if ([Link]()) return
0; int m = [Link](), n = [Link](); int[] lps = buildLPS(needle); int j = 0; for
(int i = 0; i < n; ) { if ([Link](i) == [Link](j)) { i++; j++; } if (j == m) return
i - j; else if (i < n && [Link](i) != [Link](j)) j = (j != 0) ? lps[j - 1] : 0; if
(j == 0 && (i >= n || [Link](i) != [Link](j))) i++; } return -1; } private int[]
buildLPS(String pattern) { int m = [Link](); int[] lps = new int[m]; int len = 0, i = 1;
while (i < m) { if ([Link](i) == [Link](len)) lps[i++] = ++len; else if (len != 0)
len = lps[len - 1]; else lps[i++] = 0; } return lps; } }
Time: O(n + m) Space: O(m)
Q30. Multiply Strings
Approach: Simulate grade-school multiplication digit by digit. Store partial products in an array, then convert to string.
class Solution { public String multiply(String num1, String num2) { int m = [Link](), n =
[Link](); int[] pos = new int[m + n]; for (int i = m - 1; i >= 0; i--) { for (int j = n - 1; j
>= 0; j--) { int mul = ([Link](i) - '0') * ([Link](j) - '0'); int p1 = i + j, p2 = i + j +
1; int sum = mul + pos[p2]; pos[p2] = sum % 10; pos[p1] += sum / 10; } } StringBuilder sb = new
StringBuilder(); for (int p : pos) if (!([Link]() == 0 && p == 0)) [Link](p); return
[Link]() == 0 ? "0" : [Link](); } }
Time: O(m*n) Space: O(m+n)
Q31. Remove Duplicate Characters
Approach: Use a LinkedHashSet to preserve insertion order while automatically removing duplicates.
class Solution { public String removeDuplicates(String s) { [Link]<Character> set
= new [Link]<>(); for (char c : [Link]()) [Link](c); StringBuilder sb =
new StringBuilder(); for (char c : set) [Link](c); return [Link](); } }
Time: O(n) Space: O(n)
Q32. Check Balanced Parentheses
Approach: Use a stack. Push open brackets. For each closing bracket, check if stack top matches. Stack must be
empty at end.
import [Link]; class Solution { public boolean isBalanced(String s) { Stack<Character>
stack = new Stack<>(); for (char c : [Link]()) { if (c == '(' || c == '[' || c == '{')
[Link](c); else { if ([Link]()) return false; char top = [Link](); if (c == ')' &&
top != '(') return false; if (c == ']' && top != '[') return false; if (c == '}' && top != '{')
return false; } } return [Link](); } }
Time: O(n) Space: O(n)
Q33. Reverse Words in a Sentence
Approach: Split the string by spaces, filter empty tokens, reverse the array, then join with single space.
class Solution { public String reverseWords(String s) { String[] words = [Link]().split("\\s+");
int lo = 0, hi = [Link] - 1; while (lo < hi) { String tmp = words[lo]; words[lo] = words[hi];
words[hi] = tmp; lo++; hi--; } return [Link](" ", words); } }
Time: O(n) Space: O(n)
Q34. Count and Say
Approach: Iteratively build each sequence by reading previous one: count consecutive characters and append
count+char.
class Solution { public String countAndSay(int n) { String result = "1"; for (int i = 1; i < n;
i++) { StringBuilder sb = new StringBuilder(); int j = 0; while (j < [Link]()) { char curr =
[Link](j); int count = 0; while (j < [Link]() && [Link](j) == curr) { j++;
count++; } [Link](count).append(curr); } result = [Link](); } return result; } }
Time: O(n * 2^n) Space: O(2^n)
Q35. Run-Length Encoding
Approach: Count consecutive identical characters. Append count (if > 1) followed by the character.
class Solution { public String runLengthEncoding(String s) { StringBuilder sb = new
StringBuilder(); int i = 0; while (i < [Link]()) { char curr = [Link](i); int count = 0; while
(i < [Link]() && [Link](i) == curr) { i++; count++; } if (count > 1) [Link](count);
[Link](curr); } return [Link](); } }
Time: O(n) Space: O(n)
Q36. Compare Version Numbers
Approach: Split both versions by '.'. Compare corresponding integers; treat missing parts as 0.
class Solution { public int compareVersion(String version1, String version2) { String[] v1 =
[Link]("\\."); String[] v2 = [Link]("\\."); int n = [Link]([Link], [Link]);
for (int i = 0; i < n; i++) { int a = i < [Link] ? [Link](v1[i]) : 0; int b = i <
[Link] ? [Link](v2[i]) : 0; if (a != b) return a > b ? 1 : -1; } return 0; } }
Time: O(n) Space: O(n)
Q37. Longest Prefix Suffix — KMP LPS Array
Approach: Build the KMP failure (LPS) array: lps[i] = length of longest proper prefix of pattern[0..i] that is also a suffix.
class Solution { public int[] longestPrefixSuffix(String pattern) { int n = [Link](); int[]
lps = new int[n]; int len = 0, i = 1; while (i < n) { if ([Link](i) == [Link](len))
{ lps[i++] = ++len; } else if (len != 0) { len = lps[len - 1]; // fall back } else { lps[i++] = 0; }
} return lps; // lps[n-1] is the answer for longest prefix-suffix of whole string } }
Time: O(n) Space: O(n)
Q38. String Compression
Approach: Two-pointer in-place: write pointer tracks where to write; count consecutive chars and write count+char.
class Solution { public int compress(char[] chars) { int write = 0, i = 0; while (i < [Link])
{ char curr = chars[i]; int count = 0; while (i < [Link] && chars[i] == curr) { i++; count++;
} chars[write++] = curr; if (count > 1) { for (char c : [Link](count).toCharArray())
chars[write++] = c; } } return write; } }
Time: O(n) Space: O(1)
Q39. Check if One String is a Rotation of Another
Approach: s2 is a rotation of s1 iff s2 is a substring of s1+s1 (concatenation). Use contains() or KMP.
class Solution { public boolean isRotation(String s1, String s2) { if ([Link]() != [Link]())
return false; return (s1 + s1).contains(s2); } }
Time: O(n) Space: O(n)
Q40. Check if Strings are Isomorphic
Approach: Map characters from s to t and t to s simultaneously. Any conflict in either direction means not isomorphic.
import [Link]; class Solution { public boolean isIsomorphic(String s, String t) {
HashMap<Character, Character> sToT = new HashMap<>(); HashMap<Character, Character> tToS = new
HashMap<>(); for (int i = 0; i < [Link](); i++) { char cs = [Link](i), ct = [Link](i); if
([Link](cs) && [Link](cs) != ct) return false; if ([Link](ct) && [Link](ct)
!= cs) return false; [Link](cs, ct); [Link](ct, cs); } return true; } }
Time: O(n) Space: O(1)
End of Part 1 — Arrays & Strings (Q1–Q40)
Part 2 will cover: Matrix • Stack & Queue • Tree • Heap (Q41–Q95)
Part 3 will cover: Graph • Bit Manipulation • Dynamic Programming • Greedy (Q96–Q150)