Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Longest Continuous Increasing Subsequence Implementation #800

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 76 additions & 57 deletions src/dynamic_programming/longest_continuous_increasing_subsequence.rs
Original file line number Diff line number Diff line change
@@ -1,74 +1,93 @@
pub fn longest_continuous_increasing_subsequence<T: Ord>(input_array: &[T]) -> &[T] {
let length: usize = input_array.len();
use std::cmp::Ordering;

//Handle the base cases
if length <= 1 {
return input_array;
/// Finds the longest continuous increasing subsequence in a slice.
///
/// Given a slice of elements, this function returns a slice representing
/// the longest continuous subsequence where each element is strictly
/// less than the following element.
///
/// # Arguments
///
/// * `arr` - A reference to a slice of elements
///
/// # Returns
///
/// A subslice of the input, representing the longest continuous increasing subsequence.
/// If there are multiple subsequences of the same length, the function returns the first one found.
pub fn longest_continuous_increasing_subsequence<T: Ord>(arr: &[T]) -> &[T] {
if arr.len() <= 1 {
return arr;
}

//Create the array to store the longest subsequence at each location
let mut tracking_vec = vec![1; length];
let mut start = 0;
let mut max_start = 0;
let mut max_len = 1;
let mut curr_len = 1;

//Iterate through the input and store longest subsequences at each location in the vector
for i in (0..length - 1).rev() {
if input_array[i] < input_array[i + 1] {
tracking_vec[i] = tracking_vec[i + 1] + 1;
for i in 1..arr.len() {
match arr[i - 1].cmp(&arr[i]) {
// include current element is greater than or equal to the previous
// one elements in the current increasing sequence
Ordering::Less | Ordering::Equal => {
curr_len += 1;
}
// reset when a strictly decreasing element is found
Ordering::Greater => {
if curr_len > max_len {
max_len = curr_len;
max_start = start;
}
// reset start to the current position
start = i;
// reset current length
curr_len = 1;
}
}
}

//Find the longest subsequence
let mut max_index: usize = 0;
let mut max_value: i32 = 0;
for (index, value) in tracking_vec.iter().enumerate() {
if value > &max_value {
max_value = *value;
max_index = index;
}
// final check for the last sequence
if curr_len > max_len {
max_len = curr_len;
max_start = start;
}

&input_array[max_index..max_index + max_value as usize]
&arr[max_start..max_start + max_len]
}

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

#[test]
fn test_longest_increasing_subsequence() {
//Base Cases
let base_case_array: [i32; 0] = [];
assert_eq!(
&longest_continuous_increasing_subsequence(&base_case_array),
&[]
);
assert_eq!(&longest_continuous_increasing_subsequence(&[1]), &[1]);
use super::*;

//Normal i32 Cases
assert_eq!(
&longest_continuous_increasing_subsequence(&[1, 2, 3, 4]),
&[1, 2, 3, 4]
);
assert_eq!(
&longest_continuous_increasing_subsequence(&[1, 2, 2, 3, 4, 2]),
&[2, 3, 4]
);
assert_eq!(
&longest_continuous_increasing_subsequence(&[5, 4, 3, 2, 1]),
&[5]
);
assert_eq!(
&longest_continuous_increasing_subsequence(&[5, 4, 3, 4, 2, 1]),
&[3, 4]
);
macro_rules! test_cases {
($($name:ident: $test_case:expr,)*) => {
$(
#[test]
fn $name() {
let (input, expected) = $test_case;
assert_eq!(longest_continuous_increasing_subsequence(input), expected);
}
)*
};
}

//Non-Numeric case
assert_eq!(
&longest_continuous_increasing_subsequence(&['a', 'b', 'c']),
&['a', 'b', 'c']
);
assert_eq!(
&longest_continuous_increasing_subsequence(&['d', 'c', 'd']),
&['c', 'd']
);
test_cases! {
empty_array: (&[] as &[isize], &[] as &[isize]),
single_element: (&[1], &[1]),
all_increasing: (&[1, 2, 3, 4, 5], &[1, 2, 3, 4, 5]),
all_decreasing: (&[5, 4, 3, 2, 1], &[5]),
with_equal_elements: (&[1, 2, 2, 3, 4, 2], &[1, 2, 2, 3, 4]),
increasing_with_plateau: (&[1, 2, 2, 2, 3, 3, 4], &[1, 2, 2, 2, 3, 3, 4]),
mixed_elements: (&[5, 4, 3, 4, 2, 1], &[3, 4]),
alternating_increase_decrease: (&[1, 2, 1, 2, 1, 2], &[1, 2]),
zigzag: (&[1, 3, 2, 4, 3, 5], &[1, 3]),
single_negative_element: (&[-1], &[-1]),
negative_and_positive_mixed: (&[-2, -1, 0, 1, 2, 3], &[-2, -1, 0, 1, 2, 3]),
increasing_then_decreasing: (&[1, 2, 3, 4, 3, 2, 1], &[1, 2, 3, 4]),
single_increasing_subsequence_later: (&[3, 2, 1, 1, 2, 3, 4], &[1, 1, 2, 3, 4]),
longer_subsequence_at_start: (&[5, 6, 7, 8, 9, 2, 3, 4, 5], &[5, 6, 7, 8, 9]),
longer_subsequence_at_end: (&[2, 3, 4, 10, 5, 6, 7, 8, 9], &[5, 6, 7, 8, 9]),
longest_subsequence_at_start: (&[2, 3, 4, 5, 1, 0], &[2, 3, 4, 5]),
longest_subsequence_at_end: (&[1, 7, 2, 3, 4, 5,], &[2, 3, 4, 5]),
repeated_elements: (&[1, 1, 1, 1, 1], &[1, 1, 1, 1, 1]),
}
}