Rust Bytes: Group by Frequency

Problem statement:

Given a list of integers, return a vector of vectors where each inner vector contains all numbers that appear the same number of times, grouped by frequency.

The groups should be ordered by decreasing frequency, and each group’s numbers should be sorted in ascending.

assert_eq! (group_by_frequency vec! [5, 4, 3, 2, 1]), vec! [vec! [1, 2, 3, 4, 5]l); 
assert_eq! (group_by_frequency vec! [7, 7, 7, 7]), vec! [vec! [711);
assert_eq! (group_by_frequency vec! [-1, -1, 2, 2, 3]), vec! [vec! [-1, 2], vec! [3]]);
assert_eq! (group_by_frequency vec! []), Vec::<Vec<i32>>:: new()) ;

Solution

use std::collections::HashMap;

fn group_by_frequency(nums: Vec<i32>) -> Vec<Vec<i32>> {
    // Step 1: Count frequencies using a HashMap
    let mut freq_map: HashMap<i32, usize> = HashMap::new();
    for &num in nums.iter() {
        *freq_map.entry(num).or_insert(0) += 1;
    }
    
    // Step 2: Create a frequency-to-numbers mapping
    let mut freq_to_nums: HashMap<usize, Vec<i32>> = HashMap::new();
    for (&num, &freq) in freq_map.iter() {
        freq_to_nums.entry(freq)
            .or_insert_with(Vec::new)
            .push(num);
    }
    
    // Step 3: Convert to vector of vectors and sort
    let mut result: Vec<Vec<i32>> = freq_to_nums
        .into_iter()
        .map(|(_, mut nums)| {
            nums.sort_unstable(); // Sort numbers within each group nums
        })
        .collect();
    
    // Sort groups by frequency (in descending order)
    result.sort_by_key(|group| {
        let freq = freq_map.get(&group[0]).unwrap();
        std::cmp::Reverse(*freq)
    });
    
    result
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_all_numbers_appear_once() {
        assert_eq!(
            group_by_frequency(vec![5, 4, 3, 2, 1]),
            vec![vec![1, 2, 3, 4, 5]]
        );
    }

    #[test]
    fn test_all_numbers_same() {
        assert_eq!(
            group_by_frequency(vec![7, 7, 7, 7]),
            vec![vec![7]]
        );
    }

    #[test]
    fn test_mixed_frequencies_with_negative() {
        assert_eq!(
            group_by_frequency(vec![-1, -1, 2, 2, 3]),
            vec![vec![-1, 2], vec![3]]
        );
    }

    #[test]
    fn test_empty_vector() {
        assert_eq!(
            group_by_frequency(vec![]),
            Vec::<Vec<i32>>::new()
        );
    }
}

fn main() {
    // Example usage
    let nums = vec![1, 1, 1, 2, 2, 3];
    let result = group_by_frequency(nums);
    println!("Result: {:?}", result);
}

Leave a Response