|
1 |
| -pub fn longest_continuous_increasing_subsequence<T: Ord>(input_array: &[T]) -> &[T] { |
2 |
| - let length: usize = input_array.len(); |
| 1 | +use std::cmp::Ordering; |
3 | 2 |
|
4 |
| - //Handle the base cases |
5 |
| - if length <= 1 { |
6 |
| - return input_array; |
| 3 | +/// Finds the longest continuous increasing subsequence in a slice. |
| 4 | +/// |
| 5 | +/// Given a slice of elements, this function returns a slice representing |
| 6 | +/// the longest continuous subsequence where each element is strictly |
| 7 | +/// less than the following element. |
| 8 | +/// |
| 9 | +/// # Arguments |
| 10 | +/// |
| 11 | +/// * `arr` - A reference to a slice of elements |
| 12 | +/// |
| 13 | +/// # Returns |
| 14 | +/// |
| 15 | +/// A subslice of the input, representing the longest continuous increasing subsequence. |
| 16 | +/// If there are multiple subsequences of the same length, the function returns the first one found. |
| 17 | +pub fn longest_continuous_increasing_subsequence<T: Ord>(arr: &[T]) -> &[T] { |
| 18 | + if arr.len() <= 1 { |
| 19 | + return arr; |
7 | 20 | }
|
8 | 21 |
|
9 |
| - //Create the array to store the longest subsequence at each location |
10 |
| - let mut tracking_vec = vec![1; length]; |
| 22 | + let mut start = 0; |
| 23 | + let mut max_start = 0; |
| 24 | + let mut max_len = 1; |
| 25 | + let mut curr_len = 1; |
11 | 26 |
|
12 |
| - //Iterate through the input and store longest subsequences at each location in the vector |
13 |
| - for i in (0..length - 1).rev() { |
14 |
| - if input_array[i] < input_array[i + 1] { |
15 |
| - tracking_vec[i] = tracking_vec[i + 1] + 1; |
| 27 | + for i in 1..arr.len() { |
| 28 | + match arr[i - 1].cmp(&arr[i]) { |
| 29 | + // include current element is greater than or equal to the previous |
| 30 | + // one elements in the current increasing sequence |
| 31 | + Ordering::Less | Ordering::Equal => { |
| 32 | + curr_len += 1; |
| 33 | + } |
| 34 | + // reset when a strictly decreasing element is found |
| 35 | + Ordering::Greater => { |
| 36 | + if curr_len > max_len { |
| 37 | + max_len = curr_len; |
| 38 | + max_start = start; |
| 39 | + } |
| 40 | + // reset start to the current position |
| 41 | + start = i; |
| 42 | + // reset current length |
| 43 | + curr_len = 1; |
| 44 | + } |
16 | 45 | }
|
17 | 46 | }
|
18 | 47 |
|
19 |
| - //Find the longest subsequence |
20 |
| - let mut max_index: usize = 0; |
21 |
| - let mut max_value: i32 = 0; |
22 |
| - for (index, value) in tracking_vec.iter().enumerate() { |
23 |
| - if value > &max_value { |
24 |
| - max_value = *value; |
25 |
| - max_index = index; |
26 |
| - } |
| 48 | + // final check for the last sequence |
| 49 | + if curr_len > max_len { |
| 50 | + max_len = curr_len; |
| 51 | + max_start = start; |
27 | 52 | }
|
28 | 53 |
|
29 |
| - &input_array[max_index..max_index + max_value as usize] |
| 54 | + &arr[max_start..max_start + max_len] |
30 | 55 | }
|
31 | 56 |
|
32 | 57 | #[cfg(test)]
|
33 | 58 | mod tests {
|
34 |
| - use super::longest_continuous_increasing_subsequence; |
35 |
| - |
36 |
| - #[test] |
37 |
| - fn test_longest_increasing_subsequence() { |
38 |
| - //Base Cases |
39 |
| - let base_case_array: [i32; 0] = []; |
40 |
| - assert_eq!( |
41 |
| - &longest_continuous_increasing_subsequence(&base_case_array), |
42 |
| - &[] |
43 |
| - ); |
44 |
| - assert_eq!(&longest_continuous_increasing_subsequence(&[1]), &[1]); |
| 59 | + use super::*; |
45 | 60 |
|
46 |
| - //Normal i32 Cases |
47 |
| - assert_eq!( |
48 |
| - &longest_continuous_increasing_subsequence(&[1, 2, 3, 4]), |
49 |
| - &[1, 2, 3, 4] |
50 |
| - ); |
51 |
| - assert_eq!( |
52 |
| - &longest_continuous_increasing_subsequence(&[1, 2, 2, 3, 4, 2]), |
53 |
| - &[2, 3, 4] |
54 |
| - ); |
55 |
| - assert_eq!( |
56 |
| - &longest_continuous_increasing_subsequence(&[5, 4, 3, 2, 1]), |
57 |
| - &[5] |
58 |
| - ); |
59 |
| - assert_eq!( |
60 |
| - &longest_continuous_increasing_subsequence(&[5, 4, 3, 4, 2, 1]), |
61 |
| - &[3, 4] |
62 |
| - ); |
| 61 | + macro_rules! test_cases { |
| 62 | + ($($name:ident: $test_case:expr,)*) => { |
| 63 | + $( |
| 64 | + #[test] |
| 65 | + fn $name() { |
| 66 | + let (input, expected) = $test_case; |
| 67 | + assert_eq!(longest_continuous_increasing_subsequence(input), expected); |
| 68 | + } |
| 69 | + )* |
| 70 | + }; |
| 71 | + } |
63 | 72 |
|
64 |
| - //Non-Numeric case |
65 |
| - assert_eq!( |
66 |
| - &longest_continuous_increasing_subsequence(&['a', 'b', 'c']), |
67 |
| - &['a', 'b', 'c'] |
68 |
| - ); |
69 |
| - assert_eq!( |
70 |
| - &longest_continuous_increasing_subsequence(&['d', 'c', 'd']), |
71 |
| - &['c', 'd'] |
72 |
| - ); |
| 73 | + test_cases! { |
| 74 | + empty_array: (&[] as &[isize], &[] as &[isize]), |
| 75 | + single_element: (&[1], &[1]), |
| 76 | + all_increasing: (&[1, 2, 3, 4, 5], &[1, 2, 3, 4, 5]), |
| 77 | + all_decreasing: (&[5, 4, 3, 2, 1], &[5]), |
| 78 | + with_equal_elements: (&[1, 2, 2, 3, 4, 2], &[1, 2, 2, 3, 4]), |
| 79 | + increasing_with_plateau: (&[1, 2, 2, 2, 3, 3, 4], &[1, 2, 2, 2, 3, 3, 4]), |
| 80 | + mixed_elements: (&[5, 4, 3, 4, 2, 1], &[3, 4]), |
| 81 | + alternating_increase_decrease: (&[1, 2, 1, 2, 1, 2], &[1, 2]), |
| 82 | + zigzag: (&[1, 3, 2, 4, 3, 5], &[1, 3]), |
| 83 | + single_negative_element: (&[-1], &[-1]), |
| 84 | + negative_and_positive_mixed: (&[-2, -1, 0, 1, 2, 3], &[-2, -1, 0, 1, 2, 3]), |
| 85 | + increasing_then_decreasing: (&[1, 2, 3, 4, 3, 2, 1], &[1, 2, 3, 4]), |
| 86 | + single_increasing_subsequence_later: (&[3, 2, 1, 1, 2, 3, 4], &[1, 1, 2, 3, 4]), |
| 87 | + longer_subsequence_at_start: (&[5, 6, 7, 8, 9, 2, 3, 4, 5], &[5, 6, 7, 8, 9]), |
| 88 | + longer_subsequence_at_end: (&[2, 3, 4, 10, 5, 6, 7, 8, 9], &[5, 6, 7, 8, 9]), |
| 89 | + longest_subsequence_at_start: (&[2, 3, 4, 5, 1, 0], &[2, 3, 4, 5]), |
| 90 | + longest_subsequence_at_end: (&[1, 7, 2, 3, 4, 5,], &[2, 3, 4, 5]), |
| 91 | + repeated_elements: (&[1, 1, 1, 1, 1], &[1, 1, 1, 1, 1]), |
73 | 92 | }
|
74 | 93 | }
|
0 commit comments