Bird
Raised Fist0
DSA Rustprogramming~20 mins

Collision Handling Using Chaining in DSA Rust - Practice Problems & Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Chaining Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
What is the output after inserting keys with collisions?

Consider a hash table using chaining with a simple hash function: hash(key) = key % 3. Insert keys 3, 6, 9, and 4 in that order. What is the state of the hash table buckets after all insertions?

DSA Rust
struct HashTable {
    buckets: Vec<Vec<i32>>,
}

impl HashTable {
    fn new(size: usize) -> Self {
        Self { buckets: vec![Vec::new(); size] }
    }

    fn hash(&self, key: i32) -> usize {
        (key % 3) as usize
    }

    fn insert(&mut self, key: i32) {
        let index = self.hash(key);
        self.buckets[index].push(key);
    }
}

fn main() {
    let mut table = HashTable::new(3);
    table.insert(3);
    table.insert(6);
    table.insert(9);
    table.insert(4);
    for (i, bucket) in table.buckets.iter().enumerate() {
        print!("Bucket {}: ", i);
        for key in bucket {
            print!("{} -> ", key);
        }
        println!("null");
    }
}
A
Bucket 0: 3 -&gt; 9 -&gt; null
Bucket 1: 6 -&gt; 4 -&gt; null
Bucket 2: null
B
Bucket 0: 3 -&gt; 6 -&gt; null
Bucket 1: 9 -&gt; 4 -&gt; null
Bucket 2: null
C
Bucket 0: 3 -&gt; 6 -&gt; 9 -&gt; null
Bucket 1: 4 -&gt; null
Bucket 2: null
D
Bucket 0: 3 -&gt; 6 -&gt; 9 -&gt; 4 -&gt; null
Bucket 1: null
Bucket 2: null
Attempts:
2 left
💡 Hint

Remember the hash function is key % 3. Group keys by their remainder when divided by 3.

🧠 Conceptual
intermediate
1:30remaining
Why is chaining effective for collision handling?

Which of the following best explains why chaining is a good method to handle collisions in hash tables?

AIt stores all collided keys in a linked list at the same bucket, allowing multiple keys to share one bucket without overwriting.
BIt increases the size of the hash table dynamically to avoid collisions altogether.
CIt sorts all keys in the hash table to prevent collisions.
DIt uses open addressing to find the next free bucket when a collision occurs.
Attempts:
2 left
💡 Hint

Think about how multiple keys can be stored in the same bucket without losing data.

🔧 Debug
advanced
2:00remaining
Identify the bug in this chaining insertion code

What error will this Rust code produce when inserting keys into the hash table using chaining?

DSA Rust
struct HashTable {
    buckets: Vec<Vec<i32>>,
}

impl HashTable {
    fn new(size: usize) -> Self {
        Self { buckets: vec![Vec::new(); size] }
    }

    fn hash(&self, key: i32) -> usize {
        (key % 5) as usize
    }

    fn insert(&mut self, key: i32) {
        let index = self.hash(key);
        self.buckets[index].push(key);
    }
}

fn main() {
    let mut table = HashTable::new(3);
    table.insert(8);
}
Acompiles and runs without error
Bpanic: index out of bounds at self.buckets[index].push(key)
Cpanic: division by zero error in hash function
Dsyntax error: missing semicolon
Attempts:
2 left
💡 Hint

Check the size of the buckets vector and the hash function output.

❓ Predict Output
advanced
2:00remaining
What is the output after deleting a key in chaining?

Given a hash table with chaining and the hash function hash(key) = key % 4, after inserting keys 4, 8, 12, and 5, we delete key 8. What is the state of the buckets?

DSA Rust
struct HashTable {
    buckets: Vec<Vec<i32>>,
}

impl HashTable {
    fn new(size: usize) -> Self {
        Self { buckets: vec![Vec::new(); size] }
    }

    fn hash(&self, key: i32) -> usize {
        (key % 4) as usize
    }

    fn insert(&mut self, key: i32) {
        let index = self.hash(key);
        self.buckets[index].push(key);
    }

    fn delete(&mut self, key: i32) {
        let index = self.hash(key);
        if let Some(pos) = self.buckets[index].iter().position(|&x| x == key) {
            self.buckets[index].remove(pos);
        }
    }
}

fn main() {
    let mut table = HashTable::new(4);
    table.insert(4);
    table.insert(8);
    table.insert(12);
    table.insert(5);
    table.delete(8);
    for (i, bucket) in table.buckets.iter().enumerate() {
        print!("Bucket {}: ", i);
        for key in bucket {
            print!("{} -> ", key);
        }
        println!("null");
    }
}
A
Bucket 0: 4 -&gt; 12 -&gt; null
Bucket 1: null
Bucket 2: 5 -&gt; null
Bucket 3: null
B
Bucket 0: 4 -&gt; 12 -&gt; null
Bucket 1: 5 -&gt; null
Bucket 2: null
Bucket 3: 8 -&gt; null
C
Bucket 0: 4 -&gt; 8 -&gt; 12 -&gt; null
Bucket 1: 5 -&gt; null
Bucket 2: null
Bucket 3: null
D
Bucket 0: 4 -&gt; 12 -&gt; null
Bucket 1: 5 -&gt; null
Bucket 2: null
Bucket 3: null
Attempts:
2 left
💡 Hint

Remember to remove key 8 from its bucket after insertion.

🧠 Conceptual
expert
1:30remaining
What is the average time complexity of search in chaining with uniform hashing?

Assuming a hash table uses chaining and the hash function distributes keys uniformly, what is the average time complexity to search for a key?

AO(1 + load factor) where load factor = number of keys / number of buckets
BO(n) where n is the total number of keys
CO(log n) due to sorting in chains
DO(1) always regardless of load factor
Attempts:
2 left
💡 Hint

Think about how many keys are expected in each bucket on average.

Practice

(1/5)
1. What is the main idea behind collision handling using chaining in a hash table?
easy
A. Resize the hash table when a collision occurs
B. Store all elements that hash to the same index in a linked list at that index
C. Use a second hash function to find a new index
D. Ignore collisions and overwrite existing values

Solution

  1. Step 1: Understand collision in hash tables

    When two keys hash to the same index, a collision occurs.
  2. Step 2: How chaining handles collisions

    Chaining stores all collided elements in a linked list at that index to keep them separate.
  3. Final Answer:

    Store all elements that hash to the same index in a linked list at that index -> Option B
  4. Quick Check:

    Chaining = linked list at index [OK]
Hint: Chaining means linked lists at each hash index [OK]
Common Mistakes:
  • Thinking chaining resizes the table
  • Confusing chaining with open addressing
  • Assuming collisions are ignored
2. Which of the following Rust code snippets correctly declares a hash table using chaining with vectors of linked lists?
easy
A. let mut table: Vec> = vec![None; 10];
B. let mut table: Vec<i32> = vec![0; 10];
C. let mut table: HashMap = HashMap::new();
D. let mut table: Vec = vec![Vec::new(); 10];

Solution

  1. Step 1: Identify chaining structure in Rust

    Chaining uses a vector where each element is a linked list (starting with Option) holding collided keys.
  2. Step 2: Check each option

    A declares Vec> for vector of linked list heads, correct for chaining with linked lists. B is simple Vec<i32>, no chaining. C is HashMap, built-in not manual. D is Vec, chaining with dynamic arrays not linked lists.
  3. Final Answer:

    let mut table: Vec> = vec![None; 10]; -> Option A
  4. Quick Check:

    Chaining = Vec of Option [OK]
Hint: Chaining with linked lists uses Vec> for buckets in Rust [OK]
Common Mistakes:
  • Using HashMap instead of manual vector of linked lists
  • Using simple Vec<i32> without chaining structure
  • Confusing Vec dynamic arrays with linked lists
3. Given the following Rust code using chaining for collision handling, what will be printed?
let mut table: Vec = vec![Vec::new(); 3];
let keys = [1, 4, 7];
for &key in &keys {
    let index = key % 3;
    table[index].push(key);
}
print!("{:?}", table);
medium
A. [[], [], [1, 4, 7]]
B. [[1, 4, 7], [], []]
C. [[1], [4], [7]]
D. [[], [1, 4, 7], []]

Solution

  1. Step 1: Calculate indices for each key

    1 % 3 = 1, 4 % 3 = 1, 7 % 3 = 1, so all keys go to index 1.
  2. Step 2: Check table after insertion

    table[0] = [], table[1] = [1, 4, 7], table[2] = []
  3. Final Answer:

    [[], [1, 4, 7], []] -> Option D
  4. Quick Check:

    All keys at index 1 [OK]
Hint: Calculate key % table size to find bucket [OK]
Common Mistakes:
  • Assuming keys distribute evenly
  • Mixing up modulo results
  • Printing table before insertion
4. Identify the bug in this Rust code snippet for inserting keys into a hash table using chaining:
let mut table: Vec = vec![Vec::new(); 5];
let keys = [2, 7, 25];
for key in keys {
    let index = key / 5;
    table[index].push(key);
}
medium
A. Keys array should be mutable to insert
B. The vector initialization is incorrect; should use Vec::with_capacity
C. Using division instead of modulo for index calculation causes out-of-bounds error
D. The push method is used incorrectly on the vector

Solution

  1. Step 1: Analyze index calculation

    Index is calculated as key / 5: 2/5=0, 7/5=1, 25/5=5 which is out-of-bounds (table indices 0-4).
  2. Step 2: Check vector size and index range

    Table size is 5, division can produce index >=5 causing panic. Use modulo % instead.
  3. Final Answer:

    Using division instead of modulo for index calculation causes out-of-bounds error -> Option C
  4. Quick Check:

    Index must be key % size [OK]
Hint: Use modulo (%) for index, not division (/) [OK]
Common Mistakes:
  • Using division instead of modulo
  • Ignoring vector size limits
  • Assuming keys array must be mutable
5. You want to implement a hash table with chaining in Rust that supports inserting keys and searching for a key. Which approach correctly handles collisions and allows efficient search?
hard
A. Use a Vec where each inner Vec stores keys hashed to that bucket; search by hashing key and scanning inner Vec
B. Use a single Vec<i32> and linear search for keys; ignore collisions
C. Use a HashMap and store keys as values; collisions handled internally
D. Use a Vec and replace existing keys on collision

Solution

  1. Step 1: Understand chaining for collision handling

    Chaining stores collided keys in a list at each bucket, allowing multiple keys per index.
  2. Step 2: Search method in chaining

    To search, hash the key to find the bucket, then scan the list for the key.
  3. Final Answer:

    Use a Vec where each inner Vec stores keys hashed to that bucket; search by hashing key and scanning inner Vec -> Option A
  4. Quick Check:

    Chaining = Vec of Vec + scan search [OK]
Hint: Chaining stores collisions in lists; search by bucket then scan [OK]
Common Mistakes:
  • Ignoring collisions and overwriting keys
  • Using linear search without hashing
  • Confusing HashMap with manual chaining
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard