Skip to content

Commit 905a366

Browse files
committed
feat(algorithms, array): is valid subsequence
Adds the validate subsequence algorithm solution to check if an array is a valid subsequence of another input array. Here integers are used. However, this can be modified to take in generics to where the types are comparable to check if one is a valid subsequence of another input list. This provides two approaches to the problem. One iterates through the main array checking if the first element in the subsequence equals to the first element in the array and if true, moves the `seek` pointer up by 1. If not, the `seek` pointer is checked against the length of the subsequence to check if it has reached the end and if so, then the sequence is a valid subsequence of the input array. Similar approach is applied to the second alternative solution. However, two pointers are used, were `i` is the pointer that will be used on the subsequence and `j` is the pointer that will be used on the main input array. The `while` loop condition is used to ensure that both `i` and `j` do not go over the bounds and checks if the value at pointer `i` on the sequence is equal to the value at pointer `j` on the input array. If so, then the `i` pointer is moved up by one. Either way, the `j` pointer is moved up by one along the main input array. After the loop complets, the `i` pointer is checked against the length of the sequence to verify that it reached the end. if not, then the sequence is not a valid subsequence otherwise it is regarded as a valid subsequence.
1 parent fd35635 commit 905a366

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Validate Subsequence
2+
3+
Given two non-empty arrays of integers, write a function that determines whether the second array is a subsequence of
4+
the first one.
5+
6+
A subsequence of an array is a set of numbers that aren't necessarily adjacent in the array but that are in the same
7+
order as they appear in the array. For instance, the numbers [1, 3, 4] form a subsequence of the array
8+
[1, 2, 3, 4], and so do the numbers [2, 4]. Note that a single number in an array and the array itself are both valid
9+
subsequences of the array.
10+
11+
``` plain
12+
Example 1:
13+
14+
Input: array = [5, 1, 22, 25, 6, -1, 8, 10], sequence = [1, 6, -1, 10]
15+
Output: true
16+
17+
Example 2:
18+
19+
Input: array = [5, 1, 22, 25, 6, -1, 8, 10], sequence = [5, 1, 22, 6, -1, 8, 10]
20+
Output: true
21+
Example 3:
22+
23+
Input: array = [5, 1, 22, 25, 6, -1, 8, 10], sequence = [5, 6, 1, 10, 22, 8, -1, 25]
24+
Output: false
25+
```
26+
27+
## Related Topics
28+
29+
- Array
30+
- Hash Table
31+
- Two Pointers
32+
- Binary Search
33+
- Greedy
34+
- Sorting
35+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from typing import List
2+
3+
4+
def is_valid_subsequence(array: List[int], sequence: List[int]) -> bool:
5+
"""
6+
Returns true if a sequence is a subsequence of the provided array
7+
8+
A subsequence of an array is a set of numbers that aren't necessarily adjacent in the array but that are in the same
9+
order as they appear in the array. For instance, the numbers [1, 3, 4] form a subsequence of the array
10+
[1, 2, 3, 4], and so do the numbers [2, 4]. Note that a single number in an array and the array itself are both valid
11+
subsequences of the array.
12+
13+
Time complexity: O(n) - where n is the length of the array. We iterate through the array once to find the first
14+
element in the sequence. Then, we iterate through the sequence once to check if the current element in the array is
15+
16+
Space complexity: O(1) - we only use a constant amount of extra space to store variables and do not depend on the
17+
input size.
18+
19+
Args:
20+
array (list): A non-empty array of integers.
21+
sequence (list): A non-empty array of integers.
22+
23+
Returns:
24+
A boolean that indicates whether the second array is a subsequence of the first one.
25+
"""
26+
# a sequence that is longer than the array is not a valid subsequence
27+
if len(sequence) > len(array) or len(array) == 0 or len(sequence) == 0:
28+
return False
29+
30+
seek = 0
31+
32+
for i in range(len(array)):
33+
if sequence[seek] == array[i]:
34+
seek += 1
35+
if seek == len(sequence):
36+
return True
37+
38+
return False
39+
40+
def is_valid_subsequence_v2(array: List[int], sequence: List[int]) -> bool:
41+
"""
42+
Returns true if a sequence is a subsequence of the provided array
43+
44+
A subsequence of an array is a set of numbers that aren't necessarily adjacent in the array but that are in the same
45+
order as they appear in the array. For instance, the numbers [1, 3, 4] form a subsequence of the array
46+
[1, 2, 3, 4], and so do the numbers [2, 4]. Note that a single number in an array and the array itself are both valid
47+
subsequences of the array.
48+
49+
Time complexity: O(n) - where n is the length of the array. We iterate through the array once to find the first
50+
element in the sequence. Then, we iterate through the sequence once to check if the current element in the array is
51+
52+
Space complexity: O(1) - we only use a constant amount of extra space to store variables and do not depend on the
53+
input size.
54+
55+
Args:
56+
array (list): A non-empty array of integers.
57+
sequence (list): A non-empty array of integers.
58+
59+
Returns:
60+
A boolean that indicates whether the second array is a subsequence of the first one.
61+
"""
62+
i, j = 0, 0
63+
64+
while i < len(sequence) and j < len(array):
65+
if sequence[i] == array[j]:
66+
i += 1
67+
j += 1
68+
69+
if i == len(sequence):
70+
return True
71+
return False
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import unittest
2+
from . import is_valid_subsequence, is_valid_subsequence_v2
3+
4+
5+
class IsValidSubsequenceTestCase(unittest.TestCase):
6+
def test_1(self):
7+
"""array = [5, 1, 22, 25, 6, -1, 8, 10], sequence = [1, 6, -1, 10]"""
8+
array = [5, 1, 22, 25, 6, -1, 8, 10]
9+
sequence = [1, 6, -1, 10]
10+
actual = is_valid_subsequence(array, sequence)
11+
self.assertTrue(actual)
12+
13+
def test_2(self):
14+
"""should return True for array = [5, 1, 22, 25, 6, -1, 8, 10], sequence = [5, 1, 22, 6, -1, 8, 10]"""
15+
array = [5, 1, 22, 25, 6, -1, 8, 10]
16+
sequence = [5, 1, 22, 6, -1, 8, 10]
17+
actual = is_valid_subsequence(array, sequence)
18+
self.assertTrue(actual)
19+
20+
def test_3(self):
21+
"""should return False for array = [5, 1, 22, 25, 6, -1, 8, 10], sequence = [5, 6, 1, 10, 22, 8, -1, 25]"""
22+
array = [5, 1, 22, 25, 6, -1, 8, 10]
23+
sequence = [5, 6, 1, 10, 22, 8, -1, 25]
24+
actual = is_valid_subsequence(array, sequence)
25+
self.assertFalse(actual)
26+
27+
def test_4(self):
28+
"""should return True for array = [1,2,3,4], sequence = [1,3,4]"""
29+
array = [1,2,3,4]
30+
sequence = [1,3,4]
31+
actual = is_valid_subsequence(array, sequence)
32+
self.assertTrue(actual)
33+
34+
def test_5(self):
35+
"""should return True for array = [1,2,3,4], sequence = [2,4]"""
36+
array = [1,2,3,4]
37+
sequence = [2,4]
38+
actual = is_valid_subsequence(array, sequence)
39+
self.assertTrue(actual)
40+
41+
class IsValidSubsequenceV2TestCase(unittest.TestCase):
42+
def test_1(self):
43+
"""array = [5, 1, 22, 25, 6, -1, 8, 10], sequence = [1, 6, -1, 10]"""
44+
array = [5, 1, 22, 25, 6, -1, 8, 10]
45+
sequence = [1, 6, -1, 10]
46+
actual = is_valid_subsequence_v2(array, sequence)
47+
self.assertTrue(actual)
48+
49+
def test_2(self):
50+
"""should return True for array = [5, 1, 22, 25, 6, -1, 8, 10], sequence = [5, 1, 22, 6, -1, 8, 10]"""
51+
array = [5, 1, 22, 25, 6, -1, 8, 10]
52+
sequence = [5, 1, 22, 6, -1, 8, 10]
53+
actual = is_valid_subsequence_v2(array, sequence)
54+
self.assertTrue(actual)
55+
56+
def test_3(self):
57+
"""should return False for array = [5, 1, 22, 25, 6, -1, 8, 10], sequence = [5, 6, 1, 10, 22, 8, -1, 25]"""
58+
array = [5, 1, 22, 25, 6, -1, 8, 10]
59+
sequence = [5, 6, 1, 10, 22, 8, -1, 25]
60+
actual = is_valid_subsequence_v2(array, sequence)
61+
self.assertFalse(actual)
62+
63+
def test_4(self):
64+
"""should return True for array = [1,2,3,4], sequence = [1,3,4]"""
65+
array = [1,2,3,4]
66+
sequence = [1,3,4]
67+
actual = is_valid_subsequence_v2(array, sequence)
68+
self.assertTrue(actual)
69+
70+
def test_5(self):
71+
"""should return True for array = [1,2,3,4], sequence = [2,4]"""
72+
array = [1,2,3,4]
73+
sequence = [2,4]
74+
actual = is_valid_subsequence_v2(array, sequence)
75+
self.assertTrue(actual)
76+
77+
78+
if __name__ == '__main__':
79+
unittest.main()

0 commit comments

Comments
 (0)