use std::cmp::Reverse;
use std::collections::BinaryHeap;
pub fn kway_merge_dedup(sorted_vecs: Vec<Vec<u64>>) -> Vec<u64> {
if sorted_vecs.is_empty() {
return Vec::new();
}
if sorted_vecs.len() == 1 {
return sorted_vecs.into_iter().next().unwrap();
}
let mut heap: BinaryHeap<Reverse<(u64, usize, usize)>> =
BinaryHeap::with_capacity(sorted_vecs.len());
for (i, v) in sorted_vecs.iter().enumerate() {
if !v.is_empty() {
heap.push(Reverse((v[0], i, 0)));
}
}
let total_len: usize = sorted_vecs.iter().map(|v| v.len()).sum();
let mut result = Vec::with_capacity(total_len);
let mut last: Option<u64> = None;
while let Some(Reverse((val, vec_idx, pos))) = heap.pop() {
if last != Some(val) {
result.push(val);
last = Some(val);
}
let next_pos = pos + 1;
if next_pos < sorted_vecs[vec_idx].len() {
heap.push(Reverse((sorted_vecs[vec_idx][next_pos], vec_idx, next_pos)));
}
}
result
}
pub fn merge_sorted_into(target: &mut Vec<u64>, source: &[u64]) {
if source.is_empty() {
return;
}
if target.is_empty() {
target.extend_from_slice(source);
target.dedup();
return;
}
let mut merged = Vec::with_capacity(target.len() + source.len());
let mut last_pushed: Option<u64> = None;
let mut push_unique = |val: u64| {
if last_pushed != Some(val) {
merged.push(val);
last_pushed = Some(val);
}
};
let mut i = 0;
let mut j = 0;
while i < target.len() && j < source.len() {
match target[i].cmp(&source[j]) {
std::cmp::Ordering::Less => {
push_unique(target[i]);
i += 1;
}
std::cmp::Ordering::Greater => {
push_unique(source[j]);
j += 1;
}
std::cmp::Ordering::Equal => {
push_unique(target[i]);
i += 1;
j += 1;
}
}
}
for &v in &target[i..] {
push_unique(v);
}
for &v in &source[j..] {
push_unique(v);
}
std::mem::swap(target, &mut merged);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_kway_merge_dedup_empty_input() {
let result = kway_merge_dedup(vec![]);
assert!(result.is_empty());
}
#[test]
fn test_kway_merge_dedup_single_vec() {
let input = vec![vec![1, 2, 3, 4, 5]];
let result = kway_merge_dedup(input);
assert_eq!(result, vec![1, 2, 3, 4, 5]);
}
#[test]
fn test_kway_merge_dedup_multiple_vecs_no_overlap() {
let input = vec![vec![1, 2], vec![3, 4], vec![5, 6]];
let result = kway_merge_dedup(input);
assert_eq!(result, vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn test_kway_merge_dedup_with_duplicates() {
let input = vec![vec![1, 3, 5], vec![2, 3, 6], vec![1, 4, 5]];
let result = kway_merge_dedup(input);
assert_eq!(result, vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn test_kway_merge_dedup_all_same() {
let input = vec![vec![5, 5, 5], vec![5, 5], vec![5]];
let result = kway_merge_dedup(input);
assert_eq!(result, vec![5]);
}
#[test]
fn test_kway_merge_dedup_with_empty_vecs() {
let input = vec![vec![], vec![1, 2], vec![], vec![3, 4], vec![]];
let result = kway_merge_dedup(input);
assert_eq!(result, vec![1, 2, 3, 4]);
}
#[test]
fn test_kway_merge_dedup_large_input() {
let input: Vec<Vec<u64>> = (0..100).map(|i| vec![i as u64, i as u64 + 100]).collect();
let result = kway_merge_dedup(input);
assert_eq!(result.len(), 200); assert!(result.windows(2).all(|w| w[0] < w[1]), "Should be sorted");
}
#[test]
fn test_merge_sorted_into_basic() {
let mut target = vec![1, 3, 5];
merge_sorted_into(&mut target, &[2, 4, 6]);
assert_eq!(target, vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn test_merge_sorted_into_overlapping() {
let mut target = vec![1, 2, 3, 4];
merge_sorted_into(&mut target, &[3, 4, 5, 6]);
assert_eq!(target, vec![1, 2, 3, 4, 5, 6]);
}
#[test]
fn test_merge_sorted_into_source_after_target() {
let mut target = vec![1, 2, 3];
merge_sorted_into(&mut target, &[10, 20, 30]);
assert_eq!(target, vec![1, 2, 3, 10, 20, 30]);
}
#[test]
fn test_merge_sorted_into_with_duplicates() {
let mut target = vec![1, 1, 2, 3];
merge_sorted_into(&mut target, &[2, 3, 3, 4]);
assert_eq!(target, vec![1, 2, 3, 4]);
}
#[test]
fn test_merge_sorted_into_empty_target() {
let mut target: Vec<u64> = vec![];
merge_sorted_into(&mut target, &[1, 2, 3]);
assert_eq!(target, vec![1, 2, 3]);
}
#[test]
fn test_merge_sorted_into_empty_source() {
let mut target = vec![1, 2, 3];
merge_sorted_into(&mut target, &[]);
assert_eq!(target, vec![1, 2, 3]);
}
#[test]
fn test_merge_sorted_into_source_before_target() {
let mut target = vec![10, 20, 30];
merge_sorted_into(&mut target, &[1, 2, 3]);
assert_eq!(target, vec![1, 2, 3, 10, 20, 30]);
}
#[test]
fn test_merge_sorted_into_interleaved() {
let mut target = vec![1, 5, 9];
merge_sorted_into(&mut target, &[2, 6, 10]);
assert_eq!(target, vec![1, 2, 5, 6, 9, 10]);
}
#[test]
fn test_merge_sorted_into_identical() {
let mut target = vec![1, 2, 3];
merge_sorted_into(&mut target, &[1, 2, 3]);
assert_eq!(target, vec![1, 2, 3]);
}
}