Uncategorized

C# Coding Round Quick Reference

A dense, scan-first reference for the common .NET methods and patterns — the kind of thing you could dig out of IntelliSense, but faster when it’s all on one page. Strings, collections, LINQ, the traversal skeletons, and a Big-O table.


Strings

A string is an immutable reference type. You can read s[i] but not assign it; every “change” returns a new string.

C#
string s = "hello";
s.Length;                  // 5
s[0];                      // 'h'  (a char) — cannot do s[0] = 'H'
s.Substring(2);            // "llo"
s.Substring(1, 3);         // "ell"   (startIndex, length)
s.IndexOf('l');            // 2     (-1 if not found)
s.IndexOf("lo");           // 3
s.LastIndexOf('l');        // 3
s.Contains("ell");         // true
s.StartsWith("he");        // true
s.EndsWith("lo");          // true
s.Replace("l", "L");       // "heLLo"
s.ToUpper(); s.ToLower();
s.Trim(); s.TrimStart(); s.TrimEnd();
s.Split(',');                                          // string[] on a delimiter
s.Split(' ', StringSplitOptions.RemoveEmptyEntries);   // drop empties
string.Join(",", items);   // glue an IEnumerable into one string
s.ToCharArray();           // char[]
string.IsNullOrEmpty(s);
string.IsNullOrWhiteSpace(s);
s.PadLeft(5, '0');         // "hello" -> "hello"; "42" -> "00042"
new string('x', 3);        // "xxx"
new string(charArray);     // build a string from a char[]

char helpers

C#
char.IsDigit(c);
char.IsLetter(c);
char.IsLetterOrDigit(c);
char.IsWhiteSpace(c);
char.IsUpper(c); char.IsLower(c);
char.ToUpper(c); char.ToLower(c);
c - '0';                   // int value of a digit char: '7' -> 7
(char)('a' + 1);           // 'b'

StringBuilder — mutable, use it to build strings in a loop

C#
var sb = new StringBuilder();
sb.Append("x");
sb.Append(42);
sb.AppendLine("line");
sb.Insert(0, "start");
sb.Length;
sb[i];
sb.ToString();             // materialize the final string

Parsing numbers

C#
int.Parse("42");                      // throws FormatException on bad input
int.TryParse("42", out int n);        // returns bool; n = 0 on failure (safe)
double.Parse("3.14");
double.TryParse(text, out double d);
Convert.ToInt32("42");
n.ToString();

List<T>

C#
var list = new List<int>();
var list = new List<int> { 1, 2, 3 };
list.Add(4);
list.AddRange(new[] { 5, 6 });
list.Insert(0, 9);             // insert at index
list[i];                       // index get/set — O(1)
list.Count;
list.Remove(2);                // remove first occurrence of VALUE 2 -> bool
list.RemoveAt(0);              // remove at INDEX
list.RemoveAll(x => x < 0);
list.Contains(3);              // O(n)
list.IndexOf(3);               // O(n), -1 if absent
list.Sort();                   // in place, ascending
list.Sort((a, b) => b - a);    // custom comparison (here: descending)
list.Reverse();
list.Clear();
list.ToArray();

list.Find(x => x > 2);         // first match, or default(T)
list.FindIndex(x => x > 2);    // index, or -1
list.FindAll(x => x > 2);      // List<T> of all matches
list.Exists(x => x == 2);      // bool

HashSet<T> — O(1) membership

C#
var set = new HashSet<int>();
var set = new HashSet<int> { 1, 2, 3 };
set.Add(4);                    // returns bool — false if already present
set.Remove(2);                 // returns bool
set.Contains(3);               // O(1)
set.Count;

Set operations that mutate in place (efficient — prefer these):

C#
a.UnionWith(b);                // a becomes a OR b
a.IntersectWith(b);            // a becomes a AND b
a.ExceptWith(b);               // a becomes a minus b   (great for "missing"/"unused")
a.SymmetricExceptWith(b);      // elements in exactly one
a.IsSubsetOf(b); a.IsSupersetOf(b); a.Overlaps(b); a.SetEquals(b);   // all bool

LINQ versions return a new IEnumerable (do NOT mutate, and are NOT a HashSet — materialize with .ToHashSet()):

C#
a.Union(b); a.Intersect(b); a.Except(b);     // IEnumerable<T> — add .ToHashSet()

Dictionary<K,V> — O(1) lookup by key

C#
var d = new Dictionary<string, int>();
d["a"] = 1;                    // add OR overwrite
d.Add("b", 2);                 // throws if key already exists
d["a"];                        // get — throws KeyNotFoundException if absent
d.ContainsKey("a");
d.TryGetValue("a", out int v); // bool; v = 0 if absent — the safe getter
d.GetValueOrDefault("z");      // 0 if absent
d.GetValueOrDefault("z", -1);  // custom default
d.TryAdd("a", 5);              // bool, no throw
d.Remove("a");
d.Count;
d.Keys;  d.Values;

foreach (var kvp in d) { var k = kvp.Key; var val = kvp.Value; }
foreach (var (k, val) in d) { /* deconstructed */ }

Dictionary iteration order is not guaranteed. Don’t rely on it.


Stack, Queue, PriorityQueue

C#
var st = new Stack<int>();     // LIFO — undo, DFS, backtracking
st.Push(1); st.Pop(); st.Peek(); st.Count; st.Contains(x);

var q = new Queue<int>();      // FIFO — BFS, process-in-order
q.Enqueue(1); q.Dequeue(); q.Peek(); q.Count; q.Contains(x);

var pq = new PriorityQueue<string, int>();   // <element, priority> (.NET 6+)
pq.Enqueue("task", 3);         // LOWER priority number is dequeued first
pq.Dequeue();                  // remove + return the lowest-priority element
pq.Peek(); pq.Count;
// max-first: negate the priority, or pass a custom Comparer<int> to the ctor

Arrays (1D and 2D)

C#
int[] a = new int[5];          // zero-initialized
int[] a = { 1, 2, 3 };
a.Length;
Array.Sort(a);
Array.Reverse(a);
Array.IndexOf(a, 3);
Array.Fill(a, 0);

// 2D rectangular grid:
int[,] grid = new int[rows, cols];
grid[r, c];
grid.GetLength(0);             // number of rows
grid.GetLength(1);             // number of cols

// jagged (array of arrays):
int[][] j = new int[rows][];
j[r] = new int[cols];
j[r][c];

LINQ (using System.Linq;)

C#
nums.Where(x => x > 2);                 // filter
nums.Select(x => x * 2);                // map / transform
nums.OrderBy(x => x);                    // sort ascending (stable)
nums.OrderByDescending(x => x).ThenBy(x => x.Name);
nums.Any(x => x > 2);  nums.All(x => x > 2);
nums.Count(x => x > 2);
nums.Sum();  nums.Max();  nums.Min();  nums.Average();
nums.First(x => x > 2);  nums.FirstOrDefault(x => x > 99);
nums.Distinct();
nums.Take(3);  nums.Skip(2);
nums.Contains(3);
nums.GroupBy(x => x.Key);                // IEnumerable<IGrouping<K,T>>; each group IS enumerable
nums.ToDictionary(x => x.Key, x => x.Value);
nums.ToList();  nums.ToArray();  nums.ToHashSet();
nums.Aggregate(0, (acc, x) => acc + x);  // fold / reduce

LINQ is deferred: Where/Select don’t run until you enumerate (foreach, ToList, Count…). ToList/ToArray force it once, now.


Common patterns

Frequency count:

C#
var freq = new Dictionary<char, int>();
foreach (char c in s)
    freq[c] = freq.GetValueOrDefault(c) + 1;

Bucket / group into lists:

C#
var groups = new Dictionary<string, List<int>>();
if (!groups.ContainsKey(key)) groups[key] = new List<int>();
groups[key].Add(value);

Grid: visit the 4 neighbors (with bounds check):

C#
int[] dr = { -1, 1, 0, 0 };
int[] dc = { 0, 0, -1, 1 };
for (int k = 0; k < 4; k++)
{
    int nr = r + dr[k], nc = c + dc[k];
    if (nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue;
    // visit grid[nr, nc]
}

Sort objects by a field:

C#
people.Sort((a, b) => a.Age.CompareTo(b.Age));            // in place
var sorted = people.OrderBy(p => p.Age).ThenBy(p => p.Name).ToList();   // new list

Reverse a string:

C#
var reversed = new string(s.Reverse().ToArray());

Traversal skeletons

DFS — recursive (the call stack IS the stack):

C#
var seen = new HashSet<Node>();
Visit(start);

void Visit(Node node)
{
    if (!seen.Add(node)) return;     // visited check — cycle-SAFE (won't loop forever)
    // pre-order work here
    foreach (var child in node.Children)
        Visit(child);
    // post-order work here (e.g. add to a build order)
}

To detect a cycle (not merely survive it), add a second set tracking the current path:

C#
var finished = new HashSet<Node>();
var onPath   = new HashSet<Node>();

void Visit(Node node)
{
    if (finished.Contains(node)) return;
    if (!onPath.Add(node)) throw new InvalidOperationException("cycle at " + node);
    foreach (var child in node.Children)
        Visit(child);
    onPath.Remove(node);             // step off the path on the way back up
    finished.Add(node);
}

seen/finished = won’t loop forever (safety). onPath = notices the loop (detection). Different sets, different jobs.

BFS — queue + while loop (no recursion). Use for shortest / fewest / level-by-level:

C#
var seen = new HashSet<Node>();
var q = new Queue<Node>();
seen.Add(start);
q.Enqueue(start);

while (q.Count > 0)
{
    var node = q.Dequeue();          // process on dequeue (no post-order moment)
    foreach (var child in node.Children)
        if (seen.Add(child))         // mark seen when ENQUEUING
            q.Enqueue(child);
}

Big-O cheat table

OperationListHashSetDictionaryStack/Queue
Add / Push / EnqueueO(1)*O(1)O(1)O(1)
Remove by valueO(n)O(1)O(1) by key
Contains / lookupO(n)O(1)O(1)O(n)
Index access [i]O(1)O(1) by key

\* amortized (List occasionally resizes its backing array)

AlgorithmTimeWhen
Linear scanO(n)unsorted, one-off find
Binary searchO(log n)sorted input
Sort (Array.Sort/OrderBy)O(n log n)general ordering
DFS / BFS traversalO(V + E)reach/order/components
Topological sortO(V + E)dependency / build order

Trigger → tool

The signal in the problemReach for
“seen it? / unique? / does X exist?”HashSet (O(1) membership)
“count / group / look up by key”Dictionary
“fewest steps / nearest / level-by-level”Queue → BFS
“undo / backtrack / matching / most-recent”Stack → DFS
“depends on / build order / what breaks if X changes”graph + topological sort (DFS post-order)
“parent / child / ancestor / hierarchy”tree traversal
“the input is sorted”binary search / two pointers
“always take the smallest/most-urgent next”PriorityQueue
reverse lookup is slow / “who points at me?”build the reverse map once (transpose)
nested list.Contains in a loop (O(n²))swap the inner scan for a HashSet → O(n)

Reference doc — author-written, not generated at lookup time. The thinking stays yours.

Leave a Reply

Your email address will not be published. Required fields are marked *