pub fn longest_increasing_subsequence_length(numbers: &[i32]) -> usize {
let mut tails = Vec::with_capacity(numbers.len());
for &num in numbers {
match tails.binary_search(&num) {
Ok(pos) | Err(pos) => {
if pos == tails.len() {
tails.push(num);
} else {
tails[pos] = num;
}
}
}
}
tails.len()
}
pub fn longest_increasing_subsequence(numbers: &[i32]) -> Vec<i32> {
if numbers.is_empty() {
return Vec::new();
}
let mut tails_index = Vec::with_capacity(numbers.len());
let mut prev_index = vec![-1; numbers.len()];
let mut length = 0_usize;
for (i, &num) in numbers.iter().enumerate() {
let pos =
match tails_index[..length].binary_search_by(|&idx: &usize| numbers[idx].cmp(&num)) {
Ok(pos) | Err(pos) => pos,
};
if pos == length {
tails_index.push(i);
length += 1;
} else {
tails_index[pos] = i;
}
if pos > 0 {
let pred_index = tails_index[pos - 1];
prev_index[i] = pred_index as isize;
}
}
let mut lis = Vec::with_capacity(length);
let mut curr_index = tails_index[length - 1];
while curr_index != usize::MAX {
lis.push(numbers[curr_index]);
let pi = prev_index[curr_index];
if pi < 0 {
break;
}
curr_index = pi as usize;
}
lis.reverse();
lis
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lis_length_empty() {
assert_eq!(longest_increasing_subsequence_length(&[]), 0);
}
#[test]
fn test_lis_sequence_empty() {
let seq = longest_increasing_subsequence(&[]);
assert_eq!(seq.len(), 0);
}
#[test]
fn test_lis_length_basic() {
let nums = [10, 9, 2, 5, 3, 7, 101, 18];
assert_eq!(longest_increasing_subsequence_length(&nums), 4);
let nums2 = [0, 1, 0, 3, 2, 3];
assert_eq!(longest_increasing_subsequence_length(&nums2), 4);
}
#[test]
fn test_lis_sequence_basic() {
let nums = [10, 9, 2, 5, 3, 7, 101, 18];
let seq = longest_increasing_subsequence(&nums);
assert_eq!(seq.len(), 4);
for win in seq.windows(2) {
assert!(win[0] < win[1]);
}
}
#[test]
fn test_lis_additional() {
let nums = [3, 1, 2, 1, 8, 6, 7];
let length = longest_increasing_subsequence_length(&nums);
assert_eq!(length, 4);
let seq = longest_increasing_subsequence(&nums);
assert_eq!(seq.len(), 4);
for w in seq.windows(2) {
assert!(w[0] < w[1]);
}
}
}