Menu
CoddyTech

C# Coding Interview Questions

Classic coding questions solved in idiomatic C#, each linked to a problem you can submit on the Coddy judge.

10 questions
  1. How do you reverse a string in C# without using Array.Reverse or 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 StringInfo text elements for those.

    Practice it: Reverse a String

  2. 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 with char.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 Turkish I problem).

    Practice it: Valid Palindrome

  3. 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 use GroupBy(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 by c - 'a' is faster.

    Practice it: First Unique Character in a String, Count a Character

  4. How do you find duplicate values in an array in C#?

    Add each value to a HashSet<int>; when Add returns false, 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

  5. 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 whether target - number is 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

  6. 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

  7. How do you reverse a singly linked list in C#?

    Walk the list once with prev, current and next, 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

  8. Design an LRU cache in C# with O(1) get and put.

    Combine a Dictionary from key to LinkedListNode for O(1) lookup with a LinkedList in 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, lock both methods, because the map and the list must change together.

  9. Write FizzBuzz in C#.

    Print 1 to n with Fizz for multiples of 3, Buzz for multiples of 5 and FizzBuzz for both. Check 15 first, or multiples of 15 print Fizz.

    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

  10. 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 a to z.

    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

Coddy programming languages illustration

Learn to code with Coddy

Get started