How do you reverse a string in C# without using
Array.Reverseor LINQ?Copy the characters into a
char[], swap from both ends toward the middle, and build a new string: O(n) time and space.C#using System; class Program { static string Reverse(string s) { char[] c = s.ToCharArray(); for (int i = 0, j = c.Length - 1; i < j; i++, j--) { char tmp = c[i]; c[i] = c[j]; c[j] = tmp; } return new string(c); } static void Main() { Console.WriteLine(Reverse("interview")); Console.WriteLine(Reverse("a")); Console.WriteLine(Reverse("") == ""); } }A char-by-char reverse breaks emoji and combining accents; reverse
StringInfotext elements for those.Practice it: Reverse a String
Write a C# method that checks whether a sentence is a palindrome, ignoring case and punctuation.
Use two pointers from both ends, skip characters that fail
char.IsLetterOrDigit, and compare withchar.ToLowerInvariant: O(n) time, O(1) extra space.C#using System; class Program { static bool IsPalindrome(string s) { int i = 0, j = s.Length - 1; while (i < j) { if (!char.IsLetterOrDigit(s[i])) { i++; continue; } if (!char.IsLetterOrDigit(s[j])) { j--; continue; } if (char.ToLowerInvariant(s[i]) != char.ToLowerInvariant(s[j])) return false; i++; j--; } return true; } static void Main() { Console.WriteLine(IsPalindrome("A man, a plan, a canal: Panama")); Console.WriteLine(IsPalindrome("race a car")); } }Plain
ToLower()depends on the current culture (the TurkishIproblem).Practice it: Valid Palindrome
How do you count how many times each character appears in a string in C#?
Count into a
Dictionary<char, int>in one O(n) pass, or useGroupBy(c => c). The dictionary also gives the first non-repeating character.C#using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { string s = "programming"; var counts = new Dictionary<char, int>(); foreach (char c in s) counts[c] = counts.ContainsKey(c) ? counts[c] + 1 : 1; foreach (var kv in counts.Where(kv => kv.Value > 1)) Console.Write(kv.Key + "=" + kv.Value + " "); Console.WriteLine(); char firstUnique = s.First(c => counts[c] == 1); Console.WriteLine("first unique: " + firstUnique); } }For lowercase ASCII only, an
int[26]indexed byc - 'a'is faster.Practice it: First Unique Character in a String, Count a Character
How do you find duplicate values in an array in C#?
Add each value to a
HashSet<int>; whenAddreturnsfalse, the value is a duplicate, in O(n) overall. With LINQ,GroupBy(x => x).Where(g => g.Count() > 1)does it in one expression.C#using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { int[] nums = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5 }; var seen = new HashSet<int>(); var dups = new HashSet<int>(); foreach (int n in nums) if (!seen.Add(n)) dups.Add(n); Console.WriteLine(string.Join(",", dups)); var withCounts = nums.GroupBy(n => n) .Where(g => g.Count() > 1) .Select(g => g.Key + "x" + g.Count()); Console.WriteLine(string.Join(" ", withCounts)); } }Without extra memory, sort first and compare neighbors.
Practice it: Contains Duplicate
Solve Two Sum in C#: return the indexes of the two numbers that add up to a target.
Walk the array once with a
Dictionary<int, int>from value to index, checking whethertarget - numberis already in it: O(n) time and space.C#using System; using System.Collections.Generic; class Program { static int[] TwoSum(int[] nums, int target) { var index = new Dictionary<int, int>(); for (int i = 0; i < nums.Length; i++) { int need = target - nums[i]; int j; if (index.TryGetValue(need, out j)) return new[] { j, i }; index[nums[i]] = i; } return new int[0]; } static void Main() { Console.WriteLine(string.Join(",", TwoSum(new[] { 2, 7, 11, 15 }, 9))); Console.WriteLine(string.Join(",", TwoSum(new[] { 3, 3 }, 6))); } }Look up before inserting the current number, so
[3, 3]with target 6 works and no number pairs with itself.Practice it: Two Sum, Two Sum II: Sorted Input
How do you check if a string of brackets is balanced in C#?
Push each opening bracket onto a
Stack<char>; on a closing bracket, the popped top must be its opener, and the stack must be empty at the end. O(n) time.C#using System; using System.Collections.Generic; class Program { static bool IsValid(string s) { var stack = new Stack<char>(); var pairs = new Dictionary<char, char> { { ')', '(' }, { ']', '[' }, { '}', '{' } }; foreach (char c in s) { if (c == '(' || c == '[' || c == '{') stack.Push(c); else if (stack.Count == 0 || stack.Pop() != pairs[c]) return false; } return stack.Count == 0; } static void Main() { Console.WriteLine(IsValid("{[()]}()")); Console.WriteLine(IsValid("([)]")); Console.WriteLine(IsValid("((")); } }Most failed attempts miss a closer on an empty stack or openers left at the end.
Practice it: Valid Parentheses, Min Stack
How do you reverse a singly linked list in C#?
Walk the list once with
prev,currentandnext, pointing each node back at the previous one: O(n) time, O(1) extra space.C#using System; class Node { public int Value; public Node Next; public Node(int value, Node next) { Value = value; Next = next; } } class Program { static Node Reverse(Node head) { Node prev = null, current = head; while (current != null) { Node next = current.Next; current.Next = prev; prev = current; current = next; } return prev; } static void Print(Node n) { for (; n != null; n = n.Next) Console.Write(n.Value + (n.Next != null ? " -> " : "")); Console.WriteLine(); } static void Main() { var list = new Node(1, new Node(2, new Node(3, new Node(4, null)))); Print(list); Print(Reverse(list)); } }The recursive version uses O(n) stack. Watch it in the linked list visualization.
Practice it: Reverse Linked List, Middle of the Linked List
Design an LRU cache in C# with O(1) get and put.
Combine a
Dictionaryfrom key toLinkedListNodefor O(1) lookup with aLinkedListin recency order: move a node to the front on access, and evict from the back when full.C#using System; using System.Collections.Generic; class LruCache { private readonly int capacity; private readonly Dictionary<int, LinkedListNode<KeyValuePair<int, string>>> map = new Dictionary<int, LinkedListNode<KeyValuePair<int, string>>>(); private readonly LinkedList<KeyValuePair<int, string>> order = new LinkedList<KeyValuePair<int, string>>(); public LruCache(int capacity) { this.capacity = capacity; } public string Get(int key) { LinkedListNode<KeyValuePair<int, string>> node; if (!map.TryGetValue(key, out node)) return null; order.Remove(node); order.AddFirst(node); // most recently used at the front return node.Value.Value; } public void Put(int key, string value) { LinkedListNode<KeyValuePair<int, string>> node; if (map.TryGetValue(key, out node)) order.Remove(node); else if (map.Count == capacity) { map.Remove(order.Last.Value.Key); // evict least recently used order.RemoveLast(); } map[key] = order.AddFirst(new KeyValuePair<int, string>(key, value)); } } class Program { static void Main() { var cache = new LruCache(2); cache.Put(1, "one"); cache.Put(2, "two"); cache.Get(1); // 1 is now most recent cache.Put(3, "three"); // evicts 2 Console.WriteLine(cache.Get(2) ?? "miss"); Console.WriteLine(cache.Get(1) + " " + cache.Get(3)); } }For thread safety,
lockboth methods, because the map and the list must change together.Write FizzBuzz in C#.
Print 1 to n with
Fizzfor multiples of 3,Buzzfor multiples of 5 andFizzBuzzfor both. Check 15 first, or multiples of 15 printFizz.C#using System; class Program { static void Main() { for (int i = 1; i <= 15; i++) { string s = i % 15 == 0 ? "FizzBuzz" : i % 3 == 0 ? "Fizz" : i % 5 == 0 ? "Buzz" : i.ToString(); Console.Write(s + (i < 15 ? " " : "\n")); } } }Watch the bound:
<= n, not< n.Practice it: FizzBuzz
How do you check whether two strings are anagrams in C#?
Count letters: add 1 for each character of the first string, subtract 1 for each character of the second, and the strings are anagrams if every count ends at zero. That is O(n) time and O(1) space for lowercase
atoz.using System; class Program { static bool IsAnagram(string a, string b) { if (a.Length != b.Length) return false; int[] counts = new int[26]; for (int i = 0; i < a.Length; i++) { counts[a[i] - 'a']++; counts[b[i] - 'a']--; } foreach (int c in counts) if (c != 0) return false; return true; } static void Main() { Console.WriteLine(IsAnagram("listen", "silent")); // True Console.WriteLine(IsAnagram("rat", "car")); // False } }For any Unicode text, count into a
Dictionary<char, int>instead. The one-line LINQ version,a.OrderBy(c => c).SequenceEqual(b.OrderBy(c => c)), is correct but O(n log n).Practice it: Valid Anagram
C# Coding Interview Questions
Classic coding questions solved in idiomatic C#, each linked to a problem you can submit on the Coddy judge.