Subsequence
A subsequence of an array or string is a subset of its elements in the same order as the original sequence. The elements need not be contiguous.
For example, “ace” is a subsequence of “abcdce”. All elements of the subsequence appear in the same order in the original sequence.
Key properties of a subsequence:
- Elements maintain their relative order from the original sequence
- Elements need not be adjacent or contiguous in the original sequence
- Multiple subsequences can exist within a sequence
Finding subsequences is useful for searching patterns and analyzing relationships between data.
Solution
Here is code to check if a subsequence exists:
Java
1
2
3
4
5
6
7
8
9
10
11
12
| boolean isSubsequence(String s, String seq) {
int index = 0;
for (char ch : seq.toCharArray()) {
index = s.indexOf(ch, index);
if(index == -1) return false;
index++;
}
return true;
}
|
C++
1
2
3
4
5
6
7
8
9
10
11
12
| bool isSubsequence(string s, string seq) {
int index = 0;
for (char& ch: seq) {
index = s.find(ch, index);
if (index == string::npos) return false;
index++;
}
return true;
}
|
Python
1
2
3
4
5
6
7
8
9
10
11
| def is_subsequence(s, seq):
index = 0
for ch in seq:
index = s.find(ch, index)
if index == -1:
return False
index += 1
return True
|
This iterates through the subsequence and checks if each element exists in order within the main sequence.
Subsequence matching can be customized via different matching logic as needed.
Description
A subsequence is a sequence that appears in the same relative order but not necessarily consecutively in the original sequence. In other words, from an array arr[0..n-1]
, you can form a subsequence by picking any set of elements in the same order they appear in arr
. For instance, for the array [1, 2, 3]
, the subsequences could be [1]
, [2]
, [1, 2]
, [1, 3]
, [2, 3]
, and [1, 2, 3]
among others.
Solution
Below are examples demonstrating how to find all the subsequences of a given array. We will use a recursive approach to generate the subsequences.
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| import java.util.ArrayList;
public class Subsequence {
public static void generateSubsequences(int[] arr, int index, ArrayList<Integer> current) {
if (index == arr.length) {
System.out.println(current);
return;
}
// Exclude current element
generateSubsequences(arr, index + 1, current);
// Include current element
current.add(arr[index]);
generateSubsequences(arr, index + 1, current);
current.remove(current.size() - 1);
}
public static void main(String[] args) {
int[] arr = {1, 2, 3};
generateSubsequences(arr, 0, new ArrayList<>());
}
}
|
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| #include <iostream>
#include <vector>
using namespace std;
void generateSubsequences(vector<int>& arr, int index, vector<int> current) {
if (index == arr.size()) {
for (int num : current) {
cout << num << " ";
}
cout << endl;
return;
}
// Exclude current element
generateSubsequences(arr, index + 1, current);
// Include current element
current.push_back(arr[index]);
generateSubsequences(arr, index + 1, current);
}
int main() {
vector<int> arr = {1, 2, 3};
generateSubsequences(arr, 0, {});
}
|
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| def generate_subsequences(arr, index, current):
if index == len(arr):
print(current)
return
# Exclude current element
generate_subsequences(arr, index + 1, current)
# Include current element
generate_subsequences(arr, index + 1, current + [arr[index]])
if __name__ == "__main__":
arr = [1, 2, 3]
generate_subsequences(arr, 0, [])
|
Key Takeaways
- We use recursion to explore both options for each element: either include it in the subsequence or exclude it.
- The recursion base case is when we have made decisions for all elements in the array.
- The logic remains consistent across Java, C++, and Python, differing only in syntax and data structures.