Collections and DSA typing practice
Writing algorithms in Rust is where syntax fluency stops being cosmetic. In an interview or a timed exercise, every second spent recalling whether it is .entry( or .get_mut( is a second not spent on the actual problem.
Why DSA in Rust is different
The algorithms are the same everywhere. What changes is that Rust makes you state ownership while you write them. A linked list reversal in Python is pointer reassignment; in Rust it is Option<Box<T>> and a .take() to move a value out without leaving a hole. A graph traversal that would use a plain dictionary becomes HashMap<u32, Vec<u32>> with an .entry().or_default() to avoid two lookups.
None of that is conceptually hard. It is just unfamiliar under the fingers, and unfamiliar under the fingers is expensive precisely when the clock is running.
Collection tokens
| Token | Reads as | Why it is awkward |
|---|---|---|
Vec<T> | growable array | Three letters and an angle bracket. The macro form `vec![` uses a different bracket and a bang. |
HashMap<K, V> | hash map | Two capitals inside one word, plus a comma between angle brackets. |
HashSet<T> | hash set | One character from HashMap. Autocomplete makes this worse, not better. |
VecDeque<T> | double-ended queue | Capital D in the middle, and the abbreviation is not the one most languages use. |
.entry( | get or insert slot | The idiomatic path, and the one nobody arrives at from another language. |
.or_insert( | default for a vacant entry | Only valid after `.entry(`, so it is half a token rather than a whole one. |
.push_back( | append to a deque | Different from `.push(` on Vec, and the difference is silent until it does not compile. |
.iter().copied() | borrow then own | Two chained calls that exist purely to satisfy ownership, with no analogue elsewhere. |
The counting idiom
Frequency counting appears in more algorithm problems than any other single operation. The Rust version is one line, and it is worth being able to type without thinking.
use std::collections::HashMap;
fn count(words: &[String]) -> HashMap<String, usize> {
let mut counts: HashMap<String, usize> = HashMap::new();
for word in words {
*counts.entry(word.clone()).or_insert(0) += 1;
}
counts
}The leading * is the part people forget. .or_insert( returns a mutable reference to the value, so incrementing it requires a dereference. Written without the star it does not compile, and the error message points at the arithmetic rather than the missing symbol.
Four algorithm shapes
These four cover a large share of what an interview or a practice set will ask for, and each one drills a different ownership pattern.
fn binary_search(values: &[i32], target: i32) -> Option<usize> {
let (mut left, mut right) = (0usize, values.len());
while left < right {
let mid = left + (right - left) / 2;
if values[mid] == target {
return Some(mid);
} else if values[mid] < target {
left = mid + 1;
} else {
right = mid;
}
}
None
}fn longest_unique(text: &str) -> usize {
let chars: Vec<char> = text.chars().collect();
let mut seen = HashSet::new();
let (mut left, mut best) = (0, 0);
for right in 0..chars.len() {
while seen.contains(&chars[right]) {
seen.remove(&chars[left]);
left += 1;
}
seen.insert(chars[right]);
best = best.max(right - left + 1);
}
best
}fn reverse(mut head: Option<Box<ListNode>>) -> Option<Box<ListNode>> {
let mut previous = None;
while let Some(mut node) = head {
head = node.next.take();
node.next = previous;
previous = Some(node);
}
previous
}use std::cmp::Reverse;
use std::collections::BinaryHeap;
fn top_k(numbers: &[i32], k: usize) -> Vec<i32> {
let mut heap = BinaryHeap::new();
for value in numbers {
heap.push(Reverse(*value));
if heap.len() > k {
heap.pop();
}
}
heap.into_iter().map(|Reverse(value)| value).collect()
}Practising with your own solutions
SyntaxGym does not host problem statements or reference solutions, and it does not scrape any judge site. The intended workflow is the reverse: solve the problem wherever you normally solve it, then paste your own accepted solution into the snippet library and practise typing it. Recall mode is the useful one here — it shows the signature line and blanks the body, so you rebuild the solution rather than transcribe it.
That is also the honest limit of this tool. It trains the mechanical layer so that your attention is free for the algorithm. It does not teach you the algorithm.
Frequently asked questions
- Why is *counts.entry(key).or_insert(0) += 1 written with a leading star?
- or_insert returns &mut V — a mutable reference to the value in the map, not the value itself. The dereference operator is needed to add to what the reference points at. Without it, the compiler reports a type mismatch on the addition, which sends most people looking in the wrong place.
- Is BinaryHeap a min-heap or a max-heap in Rust?
- A max-heap. To get min-heap behaviour, wrap the values in std::cmp::Reverse, which inverts the ordering. This is why top-k code in Rust is full of Reverse(...) wrapping and unwrapping, and it is a shape worth drilling because it appears nowhere else.
- Does SyntaxGym have LeetCode problems?
- No. It does not scrape or mirror problem statements, editorial solutions, or submissions from any judge. The DSA packs contain algorithm implementations written for this project. If you want to practise a specific problem, paste your own solution into the snippet library — it stays in your browser.
- Should I learn Rust basics before DSA practice?
- Yes. Algorithms in Rust combine ownership, collections, and pattern matching simultaneously. If any one of those still needs conscious thought, the algorithm practice turns into syntax practice with extra steps. The recommended order puts DSA ninth of ten for that reason.
Keep reading
- Option and Result practice
Every .get(), .pop() and .next() returns an Option. Drill it before the algorithms.
- Borrowing and ownership practice
Why .iter().copied() exists, and when you need &mut on a collection.
- Rust typing practice: the full method
The ten-step order that puts DSA where it belongs — near the end.
Try it on a real snippet
No account, nothing uploaded. Your results stay in this browser.