✨ Part 1: Linked Lists & Arrays (Problems 1–5)
✅ 1. Reverse a Linked List
��� Problem Statement:
You are given the head of a singly linked list. You need to reverse the list so that the last node becomes the first, and each node points to the previous one.
��� Approach:
We’ll use three pointers:
– prev (initially null),
– current (starts from head),
– next (temporarily stores the next node).
We loop through the list and reverse each pointer one by one.
��� Program (C#):
public class ListNode
{
public int val;
public ListNode next;
public ListNode(int val = 0, ListNode next = null)
{
this.val = val;
this.next = next;
}
}
public class Solution
{
public ListNode ReverseList(ListNode head)
{
ListNode prev = null;
ListNode current = head;
while (current != null)
{
ListNode next = current.next;
current.next = prev;
prev = current;
current = next;
}
return prev;
}
}
��� Explanation:
We reverse the list by adjusting the next pointer of each node to point to the previous node. At the end of the loop, prev becomes the new head of the reversed list.
✅ 2. Check if a String Has All Unique Characters
��� Problem Statement:
You are given a string. Check if all characters in the string are unique — no character should repeat.
��� Approach:
Use a simple nested loop to compare each character with the rest (no dictionaries used).
��� Program (C#):
public class Solution
{
public bool HasAllUniqueCharacters(string input)
{
for (int i = 0; i < input.Length; i++)
{
for (int j = i + 1; j < input.Length; j++)
{
if (input[i] == input[j])
return false;
}
}
return true;
}
}
��� Explanation:
We loop through every character and compare it with all characters after it. If we find any repetition, return false.
✅ 3. Find the Missing Number in an Array
��� Problem Statement:
You are given an array of n distinct numbers from 0 to n. One number is missing. Find that missing number.
��� Approach:
Calculate the sum of numbers from 0 to n using the formula: sum = n * (n + 1) / 2. Then subtract the sum of the given array.
��� Program (C#):
public class Solution
{
public int FindMissingNumber(int[] nums)
{
int n = nums.Length;
int totalSum = n * (n + 1) / 2;
int arraySum = 0;
for (int i = 0; i < nums.Length; i++)
{
arraySum += nums[i];
}
return totalSum – arraySum;
}
}
��� Explanation:
The difference between expected total and actual total gives us the missing number in the range.
✅ 4. Validate if a String Has Balanced Parentheses
��� Problem Statement:
You are given a string containing parentheses — (), {}, []. Check whether the string is balanced, meaning every opening has a corresponding closing bracket in the correct order.
��� Approach:
Use a manual stack simulation (array + pointer) to push opening brackets and pop them on matching closing ones.
��� Program (C#):
public class Solution
{
public bool IsBalanced(string s)
{
char[] stack = new char[s.Length];
int top = -1;
foreach (char ch in s)
{
if (ch == ‘(‘ || ch == ‘{‘ || ch == ‘[‘)
{
stack[++top] = ch;
}
else
{
if (top == -1) return false;
char open = stack[top–];
if ((ch == ‘)’ && open != ‘(‘) ||
(ch == ‘}’ && open != ‘{‘) ||
(ch == ‘]’ && open != ‘[‘))
{
return false;
}
}
}
return top == -1;
}
}
��� Explanation:
We push opening brackets and pop on matching closings. If mismatch or leftover items exist in the stack, the string is not balanced.
✅ 5. Merge Two Sorted Arrays
��� Problem Statement:
You are given two sorted arrays. Merge them into one sorted array.
��� Approach:
Use two pointers to compare both arrays and insert smaller elements one by one into a result array.
��� Program (C#):
public class Solution
{
public int[] MergeSortedArrays(int[] arr1, int[] arr2)
{
int[] result = new int[arr1.Length + arr2.Length];
int i = 0, j = 0, k = 0;
while (i < arr1.Length && j < arr2.Length)
{
if (arr1[i] < arr2[j])
result[k++] = arr1[i++];
else
result[k++] = arr2[j++];
}
while (i < arr1.Length)
result[k++] = arr1[i++];
while (j < arr2.Length)
result[k++] = arr2[j++];
return result;
}
}
��� Explanation:
We maintain three indices. The smallest current element is copied into the result array. Remaining items (if any) are copied after one array finishes.
✨ Part 2: String & Pattern Problems (Problems 6–10)
✅ 6. Validate Palindrome (case-insensitive, ignore punctuation)
��� Problem Statement:
Given a string, check whether it is a palindrome. A palindrome reads the same backward as forward. Ignore cases and non-alphanumeric characters.
��� Approach:
We can use two pointers: one starting from the beginning and one from the end. Skip characters that are not letters or digits and compare the remaining ones in lowercase.
��� Program (C#):
public class Solution
{
public bool IsPalindrome(string s)
{
int left = 0, right = s.Length – 1;
while (left < right)
{
while (left < right && !char.IsLetterOrDigit(s[left])) left++;
while (left < right && !char.IsLetterOrDigit(s[right])) right–;
if (char.ToLower(s[left]) != char.ToLower(s[right]))
return false;
left++;
right–;
}
return true;
}
}
��� Explanation:
We skip non-alphanumeric characters and compare the valid ones after converting to lowercase. If all characters match as we move inward, it’s a palindrome.
✅ 7. Reverse Words in a Sentence (preserve character order)
��� Problem Statement:
You are given a string containing words separated by spaces. Reverse the words’ positions while preserving the characters inside each word.
��� Approach:
Split the string by spaces, reverse the array of words, then join them back together with a single space.
��� Program (C#):
public class Solution
{
public string ReverseWords(string sentence)
{
string[] words = sentence.Split(‘ ‘);
Array.Reverse(words);
return string.Join(” “, words);
}
}
��� Explanation:
We split the sentence into an array of words, reverse the array, and rejoin the words using spaces.
✅ 8. Remove Duplicate Words from an Array
��� Problem Statement:
Given an array of words, remove all duplicate words and return the result.
��� Approach:
Use a simple loop to add only the first occurrence of each word to the result array.
��� Program (C#):
public class Solution
{
public string[] RemoveDuplicates(string[] words)
{
List<string> result = new List<string>();
for (int i = 0; i < words.Length; i++)
{
bool found = false;
for (int j = 0; j < result.Count; j++)
{
if (result[j] == words[i])
{
found = true;
break;
}
}
if (!found)
result.Add(words[i]);
}
return result.ToArray();
}
}
��� Explanation:
We check each word against the result list. If not already present, we add it. This avoids using HashSet or dictionary.
✅ 9. Count Occurrences of Characters (case-insensitive)
��� Problem Statement:
Given a string, count how many times each character appears. Treat uppercase and lowercase letters as the same.
��� Approach:
We loop through each character and use an array of size 26 to store counts, treating both upper and lower case as the same index.
��� Program (C#):
public class Solution
{
public int[] CountCharacterOccurrences(string input)
{
int[] counts = new int[26];
foreach (char ch in input.ToLower())
{
if (ch >= ‘a’ && ch <= ‘z’)
{
counts[ch – ‘a’]++;
}
}
return counts;
}
}
��� Explanation:
We convert the string to lowercase and count characters using a fixed-size array. Each index corresponds to a letter a–z.
✅ 10. Find the Longest Word in a Sentence
��� Problem Statement:
Given a sentence, return the longest word in it. If multiple words have the same maximum length, return the first one.
��� Approach:
Split the sentence into words and check the length of each, keeping track of the longest one found so far.
��� Program (C#):
public class Solution
{
public string FindLongestWord(string sentence)
{
string[] words = sentence.Split(‘ ‘);
string longest = “”;
foreach (string word in words)
{
if (word.Length > longest.Length)
{
longest = word;
}
}
return longest;
}
}
��� Explanation:
We split the sentence into words and loop through them to find the one with the maximum length.
✨ Part 3: Math & Number Logic (Problems 11–15)
✅ 11. Generate Fibonacci in Reverse
��� Problem Statement:
Generate the first n numbers of the Fibonacci series and return them in reverse order.
��� Approach:
Calculate the Fibonacci numbers in a loop and store them in an array, then reverse the array before returning.
��� Program (C#):
public class Solution
{
public int[] ReverseFibonacci(int n)
{
if (n <= 0) return new int[0];
if (n == 1) return new int[] { 0 };
int[] fib = new int[n];
fib[0] = 0;
fib[1] = 1;
for (int i = 2; i < n; i++)
{
fib[i] = fib[i – 1] + fib[i – 2];
}
Array.Reverse(fib);
return fib;
}
}
��� Explanation:
We build the Fibonacci sequence iteratively and reverse it at the end using Array.Reverse.
✅ 12. Find Zero-Sum Pairs
��� Problem Statement:
Given an array of integers, find all unique pairs that sum to zero.
��� Approach:
Use nested loops to check all pairs (i, j) where i < j and arr[i] + arr[j] == 0.
��� Program (C#):
public class Solution
{
public List<(int, int)> FindZeroSumPairs(int[] nums)
{
List<(int, int)> result = new List<(int, int)>();
for (int i = 0; i < nums.Length; i++)
{
for (int j = i + 1; j < nums.Length; j++)
{
if (nums[i] + nums[j] == 0)
{
result.Add((nums[i], nums[j]));
}
}
}
return result;
}
}
��� Explanation:
We compare each pair in the array and collect the pairs where the sum is zero. This is a brute-force approach without using extra data structures.
✅ 13. Prime Number Checker
��� Problem Statement:
Check whether a given number is a prime number or not.
��� Approach:
A number is prime if it is greater than 1 and divisible only by 1 and itself. We check for divisibility up to the square root of the number.
��� Program (C#):
public class Solution
{
public bool IsPrime(int num)
{
if (num <= 1) return false;
for (int i = 2; i * i <= num; i++)
{
if (num % i == 0) return false;
}
return true;
}
}
��� Explanation:
We check divisibility from 2 up to the square root of the number. If divisible, it’s not prime.
✅ 14. Factorial using Recursion
��� Problem Statement:
Write a program to compute the factorial of a number using recursion.
��� Approach:
Factorial of n is defined as n * factorial(n-1). The base case is factorial(0) = 1.
��� Program (C#):
public class Solution
{
public int Factorial(int n)
{
if (n == 0) return 1;
return n * Factorial(n – 1);
}
}
��� Explanation:
The function calls itself with a decremented value of n until it reaches 0, at which point it returns 1.
✅ 15. Merge Two Sorted Arrays without Duplicates
��� Problem Statement:
You are given two sorted arrays. Merge them into one sorted array without duplicates.
��� Approach:
Use two pointers to merge the arrays and skip duplicates while inserting into the result.
��� Program (C#):
public class Solution
{
public List<int> MergeSortedUnique(int[] arr1, int[] arr2)
{
List<int> result = new List<int>();
int i = 0, j = 0;
while (i < arr1.Length && j < arr2.Length)
{
if (arr1[i] < arr2[j])
{
if (result.Count == 0 || result[result.Count – 1] != arr1[i])
result.Add(arr1[i]);
i++;
}
else if (arr1[i] > arr2[j])
{
if (result.Count == 0 || result[result.Count – 1] != arr2[j])
result.Add(arr2[j]);
j++;
}
else
{
if (result.Count == 0 || result[result.Count – 1] != arr1[i])
result.Add(arr1[i]);
i++;
j++;
}
}
while (i < arr1.Length)
{
if (result.Count == 0 || result[result.Count – 1] != arr1[i])
result.Add(arr1[i]);
i++;
}
while (j < arr2.Length)
{
if (result.Count == 0 || result[result.Count – 1] != arr2[j])
result.Add(arr2[j]);
j++;
}
return result;
}
}
��� Explanation:
We use two pointers to compare values and only insert them into the result if they are not duplicates.
✨ Part 4: Search, Sort, and Lookup (Problems 16–20)
✅ 16. Binary Search on a Sorted Array
��� Problem Statement:
Given a sorted array and a target value, return the index of the target if found. If not found, return -1.
��� Approach:
Use the binary search technique: repeatedly divide the search interval in half, comparing the middle value to the target.
��� Program (C#):
public class Solution
{
public int BinarySearch(int[] nums, int target)
{
int left = 0, right = nums.Length – 1;
while (left <= right)
{
int mid = left + (right – left) / 2;
if (nums[mid] == target)
return mid;
else if (nums[mid] < target)
left = mid + 1;
else
right = mid – 1;
}
return -1;
}
}
��� Explanation:
We narrow the search space by half on each iteration. This gives a time complexity of O(log n).
✅ 17. Find First Non-Repeating Character
��� Problem Statement:
Given a string, return the first character that does not repeat. If all characters repeat, return a space or indicator.
��� Approach:
Use two loops: one to count occurrences of each character, and another to find the first character with a count of 1.
��� Program (C#):
public class Solution
{
public char FirstNonRepeatingCharacter(string s)
{
int[] freq = new int[256];
foreach (char c in s)
{
freq[c]++;
}
foreach (char c in s)
{
if (freq[c] == 1)
return c;
}
return ‘ ‘;
}
}
��� Explanation:
We count each character using an array. Then we check in original order for the first one with a count of 1.
✅ 18. Two Sum Problem
��� Problem Statement:
Given an array of integers and a target sum, return the indices of the two numbers that add up to the target.
��� Approach:
Use nested loops to check every pair of elements. If their sum equals the target, return their indices.
��� Program (C#):
public class Solution
{
public int[] TwoSum(int[] nums, int target)
{
for (int i = 0; i < nums.Length; i++)
{
for (int j = i + 1; j < nums.Length; j++)
{
if (nums[i] + nums[j] == target)
return new int[] { i, j };
}
}
return new int[] { -1, -1 };
}
}
��� Explanation:
We check each possible pair of numbers. Once we find two numbers whose sum equals the target, we return their indices.
✅ 19. Group Anagrams
��� Problem Statement:
Given an array of strings, group the anagrams together. Words are anagrams if they have the same characters in any order.
��� Approach:
Sort each word and compare. Words with the same sorted value are anagrams. Group them manually into lists.
��� Program (C#):
public class Solution
{
public List<List<string>> GroupAnagrams(string[] strs)
{
List<List<string>> result = new List<List<string>>();
bool[] visited = new bool[strs.Length];
for (int i = 0; i < strs.Length; i++)
{
if (visited[i]) continue;
List<string> group = new List<string> { strs[i] };
visited[i] = true;
for (int j = i + 1; j < strs.Length; j++)
{
if (!visited[j] && IsAnagram(strs[i], strs[j]))
{
group.Add(strs[j]);
visited[j] = true;
}
}
result.Add(group);
}
return result;
}
private bool IsAnagram(string s1, string s2)
{
char[] a = s1.ToCharArray();
char[] b = s2.ToCharArray();
Array.Sort(a);
Array.Sort(b);
return new string(a) == new string(b);
}
}
��� Explanation:
We check each word against others to see if they are anagrams by comparing sorted character arrays. Group matches together.
✅ 20. Find Intersection of Two Arrays
��� Problem Statement:
Given two arrays, return the intersection (common elements) between them without duplicates.
��� Approach:
Use nested loops to compare each element of the first array with the second and add only unique matches to the result.
��� Program (C#):
public class Solution
{
public List<int> Intersection(int[] nums1, int[] nums2)
{
List<int> result = new List<int>();
for (int i = 0; i < nums1.Length; i++)
{
for (int j = 0; j < nums2.Length; j++)
{
if (nums1[i] == nums2[j] && !result.Contains(nums1[i]))
{
result.Add(nums1[i]);
break;
}
}
}
return result;
}
}
��� Explanation:
We use nested loops to find common elements and check if the result already contains the value to avoid duplicates.
✨ Part 5: Stack, Queue, and Recursion (Problems 21–25)
✅ 21. Evaluate Reverse Polish Notation
��� Problem Statement:
Given an array of strings representing Reverse Polish Notation (RPN), evaluate the expression and return the result.
��� Approach:
Use a stack to process the tokens. Push numbers onto the stack and apply operations by popping two elements when an operator is found.
��� Program (C#):
public class Solution
{
public int EvalRPN(string[] tokens)
{
Stack<int> stack = new Stack<int>();
foreach (string token in tokens)
{
if (int.TryParse(token, out int num))
{
stack.Push(num);
}
else
{
int b = stack.Pop();
int a = stack.Pop();
switch (token)
{
case “+”: stack.Push(a + b); break;
case “-“: stack.Push(a – b); break;
case “*”: stack.Push(a * b); break;
case “/”: stack.Push(a / b); break;
}
}
}
return stack.Pop();
}
}
��� Explanation:
We use a stack to hold operands and apply operations in LIFO order. For each operator, we pop two numbers, compute the result, and push it back.
✅ 22. Min Stack
��� Problem Statement:
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
��� Approach:
Use an additional stack to track the current minimum after each operation.
��� Program (C#):
public class MinStack
{
private Stack<int> stack = new Stack<int>();
private Stack<int> minStack = new Stack<int>();
public void Push(int val)
{
stack.Push(val);
if (minStack.Count == 0 || val <= minStack.Peek())
minStack.Push(val);
}
public void Pop()
{
if (stack.Pop() == minStack.Peek())
minStack.Pop();
}
public int Top()
{
return stack.Peek();
}
public int GetMin()
{
return minStack.Peek();
}
}
��� Explanation:
We maintain a secondary stack that tracks the minimum values. It gets updated only when a smaller or equal value is pushed.
✅ 23. Implement Queue using Stacks
��� Problem Statement:
Implement a queue using two stacks with methods: enqueue, dequeue, and peek.
��� Approach:
Use two stacks. One for enqueue (input stack), and the other for dequeue (output stack). Transfer elements only when needed.
��� Program (C#):
public class MyQueue
{
private Stack<int> input = new Stack<int>();
private Stack<int> output = new Stack<int>();
public void Enqueue(int x)
{
input.Push(x);
}
public int Dequeue()
{
if (output.Count == 0)
{
while (input.Count > 0)
{
output.Push(input.Pop());
}
}
return output.Pop();
}
public int Peek()
{
if (output.Count == 0)
{
while (input.Count > 0)
{
output.Push(input.Pop());
}
}
return output.Peek();
}
public bool Empty()
{
return input.Count == 0 && output.Count == 0;
}
}
��� Explanation:
This approach amortizes cost by transferring elements only when necessary, making operations efficient over time.
✅ 24. Recursively Reverse a String
��� Problem Statement:
Reverse a given string using recursion and return the result.
��� Approach:
Use the recursive approach: reverse(s) = reverse(substring from index 1) + first character.
��� Program (C#):
public class Solution
{
public string ReverseString(string s)
{
if (s.Length <= 1) return s;
return ReverseString(s.Substring(1)) + s[0];
}
}
��� Explanation:
We recursively call the function on the substring and append the first character at the end until the string is fully reversed.
✅ 25. Valid Parentheses (Deep Nesting)
��� Problem Statement:
Given a string with only parentheses characters, determine if it’s valid (properly nested and matched).
��� Approach:
Use a stack to push opening brackets and pop when encountering the correct closing bracket.
��� Program (C#):
public class Solution
{
public bool IsValid(string s)
{
Stack<char> stack = new Stack<char>();
foreach (char c in s)
{
if (c == ‘(‘ || c == ‘{‘ || c == ‘[‘)
stack.Push(c);
else
{
if (stack.Count == 0) return false;
char top = stack.Pop();
if ((c == ‘)’ && top != ‘(‘) ||
(c == ‘}’ && top != ‘{‘) ||
(c == ‘]’ && top != ‘[‘))
return false;
}
}
return stack.Count == 0;
}
}
��� Explanation:
The stack helps track open brackets. Each closing bracket must match the top of the stack to be valid. Deep nesting works as long as order is preserved.
✨ Part 6: Bonus Challenges (Problems 26–30)
✅ 26. Move Zeroes to the End
��� Problem Statement:
Given an array, move all zeroes to the end while maintaining the relative order of the non-zero elements.
��� Approach:
Use two pointers: one for current element, another for tracking non-zero placement index. Swap when needed.
��� Program (C#):
public class Solution
{
public void MoveZeroes(int[] nums)
{
int index = 0;
for (int i = 0; i < nums.Length; i++)
{
if (nums[i] != 0)
{
nums[index++] = nums[i];
}
}
while (index < nums.Length)
{
nums[index++] = 0;
}
}
}
��� Explanation:
We shift all non-zero elements to the front and then fill the remaining array with zeroes.
✅ 27. Find Duplicates in an Array
��� Problem Statement:
Given an array of integers, find all elements that appear more than once.
��� Approach:
Use a nested loop to compare each element with the rest, and add to the result list if not already added.
��� Program (C#):
public class Solution
{
public List<int> FindDuplicates(int[] nums)
{
List<int> duplicates = new List<int>();
for (int i = 0; i < nums.Length; i++)
{
for (int j = i + 1; j < nums.Length; j++)
{
if (nums[i] == nums[j] && !duplicates.Contains(nums[i]))
{
duplicates.Add(nums[i]);
break;
}
}
}
return duplicates;
}
}
��� Explanation:
Each element is compared to every other. When a duplicate is found, it’s added to a result list only once.
✅ 28. Rotate Matrix 90 Degrees
��� Problem Statement:
Given an NxN 2D matrix, rotate it 90 degrees clockwise in place.
��� Approach:
First transpose the matrix (swap rows with columns), then reverse each row.
��� Program (C#):
public class Solution
{
public void Rotate(int[][] matrix)
{
int n = matrix.Length;
// Transpose
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
// Reverse each row
for (int i = 0; i < n; i++)
{
Array.Reverse(matrix[i]);
}
}
}
��� Explanation:
Transposing flips the matrix diagonally. Reversing each row completes the 90-degree clockwise rotation.
✅ 29. Pascal’s Triangle
��� Problem Statement:
Given a number of rows, generate Pascal’s Triangle up to that row.
��� Approach:
Build each row based on the previous row. The first and last values of each row are 1. Middle values are sum of two numbers above.
��� Program (C#):
public class Solution
{
public List<List<int>> GeneratePascalTriangle(int numRows)
{
List<List<int>> triangle = new List<List<int>>();
for (int i = 0; i < numRows; i++)
{
List<int> row = new List<int>();
for (int j = 0; j <= i; j++)
{
if (j == 0 || j == i)
row.Add(1);
else
row.Add(triangle[i – 1][j – 1] + triangle[i – 1][j]);
}
triangle.Add(row);
}
return triangle;
}
}
��� Explanation:
Each row is formed by adding adjacent values from the row above. The first and last values are always 1.
✅ 30. Maximum Subarray (Kadane’s Algorithm)
��� Problem Statement:
Find the contiguous subarray within an array which has the largest sum.
��� Approach:
Use Kadane’s algorithm to track current max and global max as we iterate through the array.
��� Program (C#):
public class Solution
{
public int MaxSubArray(int[] nums)
{
int maxSoFar = nums[0], maxEndingHere = nums[0];
for (int i = 1; i < nums.Length; i++)
{
maxEndingHere = Math.Max(nums[i], maxEndingHere + nums[i]);
maxSoFar = Math.Max(maxSoFar, maxEndingHere);
}
return maxSoFar;
}
}
��� Explanation:
At each step, we calculate whether to include the current element in the existing subarray or start a new one.