Make Subsequence

Last Updated : 13 Jul, 2026

Given an array a[] and another array b[]. Find the minimum number of elements to be added in b[] so that a[] becomes subsequence of b[]. Note that you can add elements at any position in b[].

Examples:

Input: a[] = [1, 2, 3, 4, 5], b[] = [2, 5, 6, 4, 9, 12]
Output: 3
Explanation: Insert 1 before 2, 3 between 2 and 5, and 4 before 5. One possible modified array is [1, 2, 3, 4, 5, 6, 4, 9, 12]. Now a[] is a subsequence of b[]. Hence, the minimum number of insertions required is 3.

Input: a[] = [1], b[] = [1]
Output: 0
Explanation: a[] is already a subsequence of b[], so no insertions are required.

[Naive Approach] Try All Insertions - O(2 ^ (n + m)) Time and O(n + m) Space

The idea is to recursively try all possibilities. Whenever the current elements do not match, either insert the current element of a into b or skip the current element of b, and return the minimum insertions required.

C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int minInsertions(int i, int j, vector<int> &a, vector<int> &b)
{

    // All elements of a are matched
    if (i == a.size())
        return 0;

    // No elements left in b, insert remaining elements of a
    if (j == b.size())
        return a.size() - i;

    // Current elements match
    if (a[i] == b[j])
        return minInsertions(i + 1, j + 1, a, b);

    // Either insert a[i] into b or skip current element of b
    return min(1 + minInsertions(i + 1, j, a, b), minInsertions(i, j + 1, a, b));
}

int makeSubsequences(vector<int> &a, vector<int> &b)
{
    return minInsertions(0, 0, a, b);
}

int main()
{
    vector<int> a = {1, 2, 3, 4, 5};
    vector<int> b = {2, 5, 6, 4, 9, 12};

    cout << makeSubsequences(a, b);

    return 0;
}
Java
import java.util.Arrays;

public class GFG {

    public static int minInsertions(int i, int j, int[] a,
                                    int[] b)
    {

        // All elements of a are matched
        if (i == a.length)
            return 0;

        // No elements left in b, insert remaining elements
        // of a
        if (j == b.length)
            return a.length - i;

        // Current elements match
        if (a[i] == b[j])
            return minInsertions(i + 1, j + 1, a, b);

        // Either insert a[i] into b or skip current element
        // of b
        return Math.min(1 + minInsertions(i + 1, j, a, b),
                        minInsertions(i, j + 1, a, b));
    }

    public static int makeSubsequences(int[] a, int[] b)
    {
        return minInsertions(0, 0, a, b);
    }

    public static void main(String[] args)
    {
        int[] a = { 1, 2, 3, 4, 5 };
        int[] b = { 2, 5, 6, 4, 9, 12 };

        System.out.println(makeSubsequences(a, b));
    }
}
Python
def minInsertions(i, j, a, b):

    # All elements of a are matched
    if i == len(a):
        return 0

    # No elements left in b, insert remaining elements of a
    if j == len(b):
        return len(a) - i

    # Current elements match
    if a[i] == b[j]:
        return minInsertions(i + 1, j + 1, a, b)

    # Either insert a[i] into b or skip current element of b
    return min(1 + minInsertions(i + 1, j, a, b), minInsertions(i, j + 1, a, b))


def makeSubsequences(a, b):
    return minInsertions(0, 0, a, b)


if __name__ == '__main__':
    a = [1, 2, 3, 4, 5]
    b = [2, 5, 6, 4, 9, 12]

    print(makeSubsequences(a, b))
C#
using System;

public class GFG {
    public static int minInsertions(int i, int j, int[] a,
                                    int[] b)
    {
        // All elements of a are matched
        if (i == a.Length)
            return 0;

        // No elements left in b, insert remaining elements
        // of a
        if (j == b.Length)
            return a.Length - i;

        // Current elements match
        if (a[i] == b[j])
            return minInsertions(i + 1, j + 1, a, b);

        // Either insert a[i] into b or skip current element
        // of b
        return Math.Min(1 + minInsertions(i + 1, j, a, b),
                        minInsertions(i, j + 1, a, b));
    }

    public static int makeSubsequences(int[] a, int[] b)
    {
        return minInsertions(0, 0, a, b);
    }

    public static void Main()
    {
        int[] a = { 1, 2, 3, 4, 5 };
        int[] b = { 2, 5, 6, 4, 9, 12 };

        Console.WriteLine(makeSubsequences(a, b));
    }
}
JavaScript
function minInsertions(i, j, a, b)
{

    // All elements of a are matched
    if (i === a.length)
        return 0;

    // No elements left in b, insert remaining elements of a
    if (j === b.length)
        return a.length - i;

    // Current elements match
    if (a[i] === b[j])
        return minInsertions(i + 1, j + 1, a, b);

    // Either insert a[i] into b or skip current element of
    // b
    return Math.min(1 + minInsertions(i + 1, j, a, b),
                    minInsertions(i, j + 1, a, b));
}

function makeSubsequences(a, b)
{
    return minInsertions(0, 0, a, b);
}

// Driver Code
const a = [ 1, 2, 3, 4, 5 ];
const b = [ 2, 5, 6, 4, 9, 12 ];

console.log(makeSubsequences(a, b));

Output
3

[Better Approach] Using LCS (Bottom-Up Tabulation) - O(n * m) Time and O(n * m) Space

The idea is to build the LCS table iteratively. Each cell stores the LCS length for prefixes of a and b. The answer is obtained by subtracting the LCS length from the size of a.

Working of Approach:

  • Create a DP table where dp[i][j] stores the LCS length for the first i elements of a and the first j elements of b.
  • Fill the table iteratively from smaller prefixes to larger prefixes.
  • If the current elements match, extend the LCS by one; otherwise, take the maximum of the adjacent states.
  • The last cell of the table contains the length of the LCS of the two arrays.
  • The minimum insertions required are a.size() - dp[n][m].

Let us understand with an example:
Input: a[] = [1, 2, 3, 4, 5], b[] = [2, 5, 6, 4, 9, 12]

  • Create a DP table where dp[i][j] stores the LCS length between the first i elements of a and the first j elements of b.
  • Traverse both arrays and fill the table by matching equal elements or taking the maximum of the previous states.
  • For the given input, the computed LCS is [2, 5], so dp[5][6] = 2.
  • This means 2 elements of a are already present in b in the correct order.
  • Hence, the minimum insertions required are 5 - 2 = 3.
C++
#include <iostream>
#include <vector>
using namespace std;

int makeSubsequences(vector<int> &a, vector<int> &b)
{
    int n = a.size();
    int m = b.size();

    // dp[i][j] stores the length of the LCS between
    // the first i elements of a and the first j elements of b
    vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));

    // Build the LCS table
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            // Current elements match
            if (a[i - 1] == b[j - 1])
                dp[i][j] = 1 + dp[i - 1][j - 1];

            // Current elements do not match
            else
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
        }
    }

    // Remaining elements of a must be inserted
    return n - dp[n][m];
}

int main()
{
    vector<int> a = {1, 2, 3, 4, 5};
    vector<int> b = {2, 5, 6, 4, 9, 12};

    cout << makeSubsequences(a, b);

    return 0;
}
Java
import java.util.*;

public class GFG {

    static int makeSubsequences(int[] a, int[] b)
    {
        int n = a.length;
        int m = b.length;

        // dp[i][j] stores the length of the LCS between
        // the first i elements of a and the first j
        // elements of b
        int[][] dp = new int[n + 1][m + 1];

        // Build the LCS table
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {

                // Current elements match
                if (a[i - 1] == b[j - 1])
                    dp[i][j] = 1 + dp[i - 1][j - 1];

                // Current elements do not match
                else
                    dp[i][j] = Math.max(dp[i - 1][j],
                                        dp[i][j - 1]);
            }
        }

        // Remaining elements of a must be inserted
        return n - dp[n][m];
    }

    public static void main(String[] args)
    {
        int[] a = { 1, 2, 3, 4, 5 };
        int[] b = { 2, 5, 6, 4, 9, 12 };

        System.out.println(makeSubsequences(a, b));
    }
}
Python
from typing import List


def makeSubsequences(a: List[int], b: List[int]) -> int:
    n = len(a)
    m = len(b)

    # dp[i][j] stores the length of the LCS between
    # the first i elements of a and the first j elements of b
    dp = [[0] * (m + 1) for _ in range(n + 1)]

    # Build the LCS table
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            # Current elements match
            if a[i - 1] == b[j - 1]:
                dp[i][j] = 1 + dp[i - 1][j - 1]
            # Current elements do not match
            else:
                dp[i][j] = max(dp[i - 1][j], dp[i][j - 1])

    # Remaining elements of a must be inserted
    return n - dp[n][m]


if __name__ == '__main__':
    a = [1, 2, 3, 4, 5]
    b = [2, 5, 6, 4, 9, 12]

    print(makeSubsequences(a, b))
C#
using System;

public class GFG {
    static int makeSubsequences(int[] a, int[] b)
    {
        int n = a.Length;
        int m = b.Length;

        // dp[i][j] stores the length of the LCS between
        // the first i elements of a and the first j
        // elements of b
        int[, ] dp = new int[n + 1, m + 1];

        // Build the LCS table
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                // Current elements match
                if (a[i - 1] == b[j - 1])
                    dp[i, j] = 1 + dp[i - 1, j - 1];

                // Current elements do not match
                else
                    dp[i, j] = Math.Max(dp[i - 1, j],
                                        dp[i, j - 1]);
            }
        }

        // Remaining elements of a must be inserted
        return n - dp[n, m];
    }

    public static void Main()
    {
        int[] a = { 1, 2, 3, 4, 5 };
        int[] b = { 2, 5, 6, 4, 9, 12 };

        Console.WriteLine(makeSubsequences(a, b));
    }
}
JavaScript
function makeSubsequences(a, b)
{
    let n = a.length;
    let m = b.length;

    // dp[i][j] stores the length of the LCS between
    // the first i elements of a and the first j elements of
    // b
    let dp = Array.from({length : n + 1},
                        () => Array(m + 1).fill(0));

    // Build the LCS table
    for (let i = 1; i <= n; i++) {
        for (let j = 1; j <= m; j++) {
            // Current elements match
            if (a[i - 1] === b[j - 1]) {
                dp[i][j] = 1 + dp[i - 1][j - 1];
            }
            // Current elements do not match
            else {
                dp[i][j]
                    = Math.max(dp[i - 1][j], dp[i][j - 1]);
            }
        }
    }

    // Remaining elements of a must be inserted
    return n - dp[n][m];
}

// Driver Code
let a = [ 1, 2, 3, 4, 5 ];
let b = [ 2, 5, 6, 4, 9, 12 ];

console.log(makeSubsequences(a, b));

Output
3

[Expected Approach] Using LCS (Space Optimized DP) - O(n * m) Time and O(m) Space

The idea is to compute the Longest Common Subsequence (LCS) between a and b using a space-optimized DP table. The LCS gives the maximum number of elements already present in the correct order, so the remaining elements of a must be inserted into b.

Working of Approach:

  • Create two DP rows to store the LCS values for the current and previous rows.
  • Traverse both arrays and update the current row based on whether the current elements match.
  • If the elements match, extend the LCS by one; otherwise, take the maximum of the left and upper values.
  • Reuse the two rows for every iteration to reduce the auxiliary space from O(n × m) to O(m).
  • The minimum insertions required are a.size() - length of the LCS.

Let us understand with an example:
Input: a[] = [1, 2, 3, 4, 5], b[] = [2, 5, 6, 4, 9, 12]

  • Create two DP rows to store the LCS values for the previous and current iterations.
  • Traverse both arrays and update the current row. Matching elements increase the LCS length, while non-matching elements take the maximum of the left and upper values.
  • After processing all elements, the last computed LCS length is 2, corresponding to the subsequence [2, 5].
  • Thus, 2 elements of a already appear in b in the correct order, and the remaining 3 elements must be inserted.
  • Therefore, the minimum insertions required are 5 - 2 = 3.
C++
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

// Returns length of LCS
int lcs(vector<int> &a, vector<int> &b)
{
    int n = a.size();
    int m = b.size();

    vector<vector<int>> dp(2, vector<int>(m + 1, 0));

    // Binary index, used to
    // index current row and
    // previous row.
    bool bi;

    for (int i = 0; i <= n; i++)
    {

        // Compute current
        // binary index
        bi = i & 1;

        for (int j = 0; j <= m; j++)
        {
            if (i == 0 || j == 0)
                dp[bi][j] = 0;

            else if (a[i - 1] == b[j - 1])
                dp[bi][j] = dp[1 - bi][j - 1] + 1;

            else
                dp[bi][j] = max(dp[1 - bi][j], dp[bi][j - 1]);
        }
    }

    // Last filled entry contains
    // length of LCS
    // for a[0..n-1] and b[0..m-1]
    return dp[bi][m];
}

int makeSubsequences(vector<int> &a, vector<int> &b)
{

    // Required answer is length of Array a minus
    // length of longest common subsequence of a & b.
    int ans = a.size() - lcs(a, b);

    return ans;
}

int main()
{
    vector<int> a = {1, 2, 3, 4, 5};
    vector<int> b = {2, 5, 6, 4, 9, 12};

    cout << makeSubsequences(a, b);

    return 0;
}
Java
public class GFG {

    // Returns length of LCS
    static int lcs(int[] a, int[] b)
    {
        int n = a.length;
        int m = b.length;

        int[][] dp = new int[2][m + 1];

        // Binary index, used to
        // index current row and
        // previous row.
        int bi = 0;

        for (int i = 0; i <= n; i++) {

            // Compute current
            // binary index
            bi = i & 1;

            for (int j = 0; j <= m; j++) {
                if (i == 0 || j == 0) {
                    dp[bi][j] = 0;
                }

                else if (a[i - 1] == b[j - 1]) {
                    dp[bi][j] = dp[1 - bi][j - 1] + 1;
                }

                else {
                    dp[bi][j] = Math.max(dp[1 - bi][j],
                                         dp[bi][j - 1]);
                }
            }
        }

        // Last filled entry contains
        // length of LCS
        // for a[0..n-1] and b[0..m-1]
        return dp[bi][m];
    }

    static int makeSubsequences(int[] a, int[] b)
    {

        // Required answer is length of Array a minus
        // length of longest common subsequence of a & b.
        int ans = a.length - lcs(a, b);

        return ans;
    }

    public static void main(String[] args)
    {
        int[] a = { 1, 2, 3, 4, 5 };
        int[] b = { 2, 5, 6, 4, 9, 12 };

        System.out.println(makeSubsequences(a, b));
    }
}
Python
# Returns length of LCS
def lcs(a, b):
    n = len(a)
    m = len(b)

    dp = [[0] * (m + 1) for _ in range(2)]

    # Binary index, used to
    # index current row and
    # previous row.
    bi = 0

    for i in range(n + 1):

        # Compute current
        # binary index
        bi = i & 1

        for j in range(m + 1):
            if i == 0 or j == 0:
                dp[bi][j] = 0

            elif a[i - 1] == b[j - 1]:
                dp[bi][j] = dp[1 - bi][j - 1] + 1

            else:
                dp[bi][j] = max(dp[1 - bi][j], dp[bi][j - 1])

    # Last filled entry contains
    # length of LCS
    # for a[0..n-1] and b[0..m-1]
    return dp[bi][m]


def makeSubsequences(a, b):

    # Required answer is length of Array a minus
    # length of longest common subsequence of a & b.
    ans = len(a) - lcs(a, b)

    return ans


if __name__ == "__main__":
    a = [1, 2, 3, 4, 5]
    b = [2, 5, 6, 4, 9, 12]

    print(makeSubsequences(a, b))
C#
using System;

public class GFG {
    // Returns length of LCS
    static int lcs(int[] a, int[] b)
    {
        int n = a.Length;
        int m = b.Length;

        int[, ] dp = new int[2, m + 1];

        // Binary index, used to
        // index current row and
        // previous row.
        int bi = 0;

        for (int i = 0; i <= n; i++) {
            // Compute current binary index
            bi = i & 1;

            for (int j = 0; j <= m; j++) {
                if (i == 0 || j == 0) {
                    dp[bi, j] = 0;
                }
                else if (a[i - 1] == b[j - 1]) {
                    dp[bi, j] = dp[1 - bi, j - 1] + 1;
                }
                else {
                    dp[bi, j] = Math.Max(dp[1 - bi, j],
                                         dp[bi, j - 1]);
                }
            }
        }

        // Last filled entry contains
        // length of LCS
        // for a[0..n-1] and b[0..m-1]
        return dp[bi, m];
    }

    static int makeSubsequences(int[] a, int[] b)
    {
        // Required answer is length of Array a minus
        // length of longest common subsequence of a & b.
        int ans = a.Length - lcs(a, b);
        return ans;
    }

    public static void Main()
    {
        int[] a = { 1, 2, 3, 4, 5 };
        int[] b = { 2, 5, 6, 4, 9, 12 };

        Console.WriteLine(makeSubsequences(a, b));
    }
}
JavaScript
function lcs(a, b)
{
    // Returns length of LCS
    let n = a.length;
    let m = b.length;

    let dp = new Array(2).fill(null).map(
        () => new Array(m + 1).fill(0));

    // Binary index, used to
    // index current row and
    // previous row.
    let bi;

    for (let i = 0; i <= n; i++) {

        // Compute current
        // binary index
        bi = i % 2 === 1;

        for (let j = 0; j <= m; j++) {
            if (i === 0 || j === 0)
                dp[bi ? 1 : 0][j] = 0;

            else if (a[i - 1] === b[j - 1])
                dp[bi ? 1 : 0][j]
                    = dp[bi ? 0 : 1][j - 1] + 1;

            else
                dp[bi ? 1 : 0][j]
                    = Math.max(dp[bi ? 0 : 1][j],
                               dp[bi ? 1 : 0][j - 1]);
        }
    }

    // Last filled entry contains
    // length of LCS
    // for a[0..n-1] and b[0..m-1]
    return dp[bi ? 1 : 0][m];
}

function makeSubsequences(a, b)
{

    // Required answer is length of Array a minus
    // length of longest common subsequence of a & b.
    let ans = a.length - lcs(a, b);

    return ans;
}

// Driver Code
let a = [ 1, 2, 3, 4, 5 ];
let b = [ 2, 5, 6, 4, 9, 12 ];

console.log(makeSubsequences(a, b));

Output
3
Comment