Open In App

Longest Common Increasing Subsequence (LCS + LIS)

Improve
Improve
Like Article
Like
Save
Share
Report

Prerequisites : LCS, LIS

Given two arrays, find length of the longest common increasing subsequence [LCIS] and print one of such sequences (multiple sequences may exist)
Suppose we consider two arrays – 
arr1[] = {3, 4, 9, 1} and 
arr2[] = {5, 3, 8, 9, 10, 2, 1}
Our answer would be {3, 9} as this is the longest common subsequence which is increasing also.

The idea is to use dynamic programming here as well. We store the longest common increasing sub-sequence ending at each index of arr2[]. We create an auxiliary array table[] such that table[j] stores length of LCIS ending with arr2[j]. At the end, we return maximum value from this table. For filling values in this table, we traverse all elements of arr1[] and for every element arr1[i], we traverse all elements of arr2[]. If we find a match, we update table[j] with length of current LCIS. To maintain current LCIS, we keep checking valid table[j] values.

Below is the program to find length of LCIS. 

C++




// A C++ Program to find length of the Longest Common
// Increasing Subsequence (LCIS)
#include<bits/stdc++.h>
using namespace std;
 
// Returns the length and the LCIS of two
// arrays arr1[0..n-1] and arr2[0..m-1]
int LCIS(int arr1[], int n, int arr2[], int m)
{
    // table[j] is going to store length of LCIS
    // ending with arr2[j]. We initialize it as 0,
    int table[m];
    for (int j=0; j<m; j++)
        table[j] = 0;
 
    // Traverse all elements of arr1[]
    for (int i=0; i<n; i++)
    {
        // Initialize current length of LCIS
        int current = 0;
 
        // For each element of arr1[], traverse all
        // elements of arr2[].
        for (int j=0; j<m; j++)
        {
            // If both the array have same elements.
            // Note that we don't break the loop here.
            if (arr1[i] == arr2[j])
                if (current + 1 > table[j])
                    table[j] = current + 1;
 
            /* Now seek for previous smaller common
               element for current element of arr1 */
            if (arr1[i] > arr2[j])
                if (table[j] > current)
                    current = table[j];
        }
    }
 
    // The maximum value in table[] is out result
    int result = 0;
    for (int i=0; i<m; i++)
        if (table[i] > result)
           result = table[i];
 
    return result;
}
 
/* Driver program to test above function */
int main()
{
    int arr1[] = {3, 4, 9, 1};
    int arr2[] = {5, 3, 8, 9, 10, 2, 1};
 
    int n = sizeof(arr1)/sizeof(arr1[0]);
    int m = sizeof(arr2)/sizeof(arr2[0]);
 
    cout << "Length of LCIS is "
         << LCIS(arr1, n, arr2, m);
    return (0);
}


Java




// A Java Program to find length of the Longest
// Common Increasing Subsequence (LCIS)
import java.io.*;
 
class GFG {
 
    // Returns the length and the LCIS of two
    // arrays arr1[0..n-1] and arr2[0..m-1]
    static int LCIS(int arr1[], int n, int arr2[],
                                         int m)
    {
        // table[j] is going to store length of
        // LCIS ending with arr2[j]. We initialize
        // it as 0,
        int table[] = new int[m];
        for (int j = 0; j < m; j++)
            table[j] = 0;
 
        // Traverse all elements of arr1[]
        for (int i = 0; i < n; i++)
        {
            // Initialize current length of LCIS
            int current = 0;
 
            // For each element of arr1[], traverse
            // all elements of arr2[].
            for (int j = 0; j < m; j++)
            {
                // If both the array have same
                // elements. Note that we don't
                // break the loop here.
                if (arr1[i] == arr2[j])
                    if (current + 1 > table[j])
                        table[j] = current + 1;
 
                /* Now seek for previous smaller
                common element for current
                element of arr1 */
                if (arr1[i] > arr2[j])
                    if (table[j] > current)
                        current = table[j];
            }
        }
 
        // The maximum value in table[] is out
        // result
        int result = 0;
        for (int i=0; i<m; i++)
            if (table[i] > result)
            result = table[i];
 
        return result;
    }
 
    /* Driver program to test above function */
    public static void main(String[] args)
    {
        int arr1[] = {3, 4, 9, 1};
        int arr2[] = {5, 3, 8, 9, 10, 2, 1};
 
        int n = arr1.length;
        int m = arr2.length;
 
    System.out.println("Length of LCIS is " +
                       LCIS(arr1, n, arr2, m));
    }
}
// This code is contributed by Prerna Saini


Python 3




# Python 3 Program to find length of the
# Longest Common Increasing Subsequence (LCIS)
 
# Returns the length and the LCIS of two
# arrays arr1[0..n-1] and arr2[0..m-1]
def LCIS(arr1, n, arr2, m):
 
    # table[j] is going to store length of LCIS
    # ending with arr2[j]. We initialize it as 0,
    table = [0] * m
    for j in range(m):
        table[j] = 0
 
    # Traverse all elements of arr1[]
    for i in range(n):
     
        # Initialize current length of LCIS
        current = 0
 
        # For each element of arr1[],
        # traverse all elements of arr2[].
        for j in range(m):
             
            # If both the array have same elements.
            # Note that we don't break the loop here.
            if (arr1[i] == arr2[j]):
                if (current + 1 > table[j]):
                    table[j] = current + 1
 
            # Now seek for previous smaller common
            # element for current element of arr1
            if (arr1[i] > arr2[j]):
                if (table[j] > current):
                    current = table[j]
 
    # The maximum value in table[]
    # is out result
    result = 0
    for i in range(m):
        if (table[i] > result):
            result = table[i]
 
    return result
 
# Driver Code
if __name__ == "__main__":
     
    arr1 = [3, 4, 9, 1]
    arr2 = [5, 3, 8, 9, 10, 2, 1]
 
    n = len(arr1)
    m = len(arr2)
 
    print("Length of LCIS is",
           LCIS(arr1, n, arr2, m))
 
# This code is contributed by ita_c


C#




// A C# Program to find length of the Longest
// Common Increasing Subsequence (LCIS)
using System;
 
class GFG {
 
    // Returns the length and the LCIS of two
    // arrays arr1[0..n-1] and arr2[0..m-1]
    static int LCIS(int []arr1, int n,
                    int []arr2, int m)
    {
        // table[j] is going to store length of
        // LCIS ending with arr2[j]. We initialize
        // it as 0,
        int []table = new int[m];
        for (int j = 0; j < m; j++)
            table[j] = 0;
 
        // Traverse all elements of arr1[]
        for (int i = 0; i < n; i++)
        {
            // Initialize current length of LCIS
            int current = 0;
 
            // For each element of arr1[], traverse
            // all elements of arr2[].
            for (int j = 0; j < m; j++)
            {
                // If both the array have same
                // elements. Note that we don't
                // break the loop here.
                if (arr1[i] == arr2[j])
                    if (current + 1 > table[j])
                        table[j] = current + 1;
 
                /* Now seek for previous smaller
                   common element for current
                   element of arr1 */
                if (arr1[i] > arr2[j])
                    if (table[j] > current)
                        current = table[j];
            }
        }
 
        // The maximum value in
        // table[] is out result
        int result = 0;
        for (int i = 0; i < m; i++)
            if (table[i] > result)
            result = table[i];
 
        return result;
    }
 
    /* Driver program to test above function */
    public static void Main()
    {
        int []arr1 = {3, 4, 9, 1};
        int []arr2 = {5, 3, 8, 9, 10, 2, 1};
 
        int n = arr1.Length;
        int m = arr2.Length;
 
    Console.Write("Length of LCIS is " +
                   LCIS(arr1, n, arr2, m));
    }
}
 
// This code is contributed by nitin mittal.


Javascript




<script>
 
// Javascript Program to find length of the Longest
// Common Increasing Subsequence (LCIS)
 
    // Returns the length and the LCIS of two
    // arrays arr1[0..n-1] and arr2[0..m-1]
    function LCIS(arr1, n, arr2, m)
    {
        // table[j] is going to store length of
        // LCIS ending with arr2[j]. We initialize
        // it as 0,
        let table = [];
        for (let j = 0; j < m; j++)
            table[j] = 0;
   
        // Traverse all elements of arr1[]
        for (let i = 0; i < n; i++)
        {
            // Initialize current length of LCIS
            let current = 0;
   
            // For each element of arr1[], traverse
            // all elements of arr2[].
            for (let j = 0; j < m; j++)
            {
                // If both the array have same
                // elements. Note that we don't
                // break the loop here.
                if (arr1[i] == arr2[j])
                    if (current + 1 > table[j])
                        table[j] = current + 1;
   
                /* Now seek for previous smaller
                common element for current
                element of arr1 */
                if (arr1[i] > arr2[j])
                    if (table[j] > current)
                        current = table[j];
            }
        }
   
        // The maximum value in table[] is out
        // result
        let result = 0;
        for (let i=0; i<m; i++)
            if (table[i] > result)
            result = table[i];
   
        return result;
    }
   
 
// Driver Code
 
        let arr1 = [3, 4, 9, 1];
        let arr2 = [5, 3, 8, 9, 10, 2, 1];
   
        let n = arr1.length;
        let m = arr2.length;
   
    document.write("Length of LCIS is " +
                       LCIS(arr1, n, arr2, m));
                       
</script>


PHP




<?php
// PHP Program to find length of
// the Longest Common Increasing
// Subsequence (LCIS)
 
// Returns the length and the LCIS
// of two arrays arr1[0..n-1] and
// arr2[0..m-1]
function LCIS($arr1, $n, $arr2, $m)
{
    // table[j] is going to store
    // length of LCIS ending with
    // arr2[j]. We initialize it as 0,
     
    $table = Array();
     
    //int table[m];
    for ($j = 0; $j < $m; $j++)
        $table[$j] = 0;
 
    // Traverse all elements of arr1[]
    for ($i = 0; $i < $n; $i++)
    {
        // Initialize current
        // length of LCIS
        $current = 0;
 
        // For each element of
        // arr1[], traverse all
        // elements of arr2[].
        for ($j = 0; $j < $m; $j++)
        {
            // If both the array have
            // same elements. Note that
            // we don't break the loop here.
            if ($arr1[$i] == $arr2[$j])
                if ($current + 1 > $table[$j])
                    $table[$j] = $current + 1;
 
            /* Now seek for previous smaller
            common element for current
            element of arr1 */
            if ($arr1[$i] > $arr2[$j])
                if ($table[$j] > $current)
                    $current = $table[$j];
        }
    }
 
    // The maximum value in
    // table[] is out result
    $result = 0;
    for ($i = 0; $i < $m; $i++)
        if ($table[$i] > $result)
        $result = $table[$i];
 
    return $result;
}
 
// Driver Code
$arr1 = array (3, 4, 9, 1);
$arr2 = array (5, 3, 8, 9, 10, 2, 1);
 
$n = sizeof($arr1);
$m = sizeof($arr2);
 
echo "Length of LCIS is ",
       LCIS($arr1, $n, $arr2, $m);
 
// This code is contributed by ajit
?>


Output

Length of LCIS is 2






Time Complexity: O(n*m), where n and m represents the size of the given two arrays.
Auxiliary Space: O(m), where m represents the size of the given second array.

Approach#2: Using brute force

We can find the longest common increasing subsequence (LCIS) of two arrays by using dynamic programming. We will use a matrix dp[][] to store the LCIS of two arrays. The dp[i][j] will represent the length of the LCIS that ends at the i-th index of arr1 and j-th index of arr2. We can compute the dp matrix by iterating through each element of arr1 and arr2 and updating the matrix based on the following conditions:

If arr1[i] and arr2[j] are equal, then dp[i][j] = 1 + max(dp[k][l]) where 0 ? k < i and 0 ? l < j.
If arr1[i] and arr2[j] are not equal, then dp[i][j] = max(dp[k][j]) where 0 ? k < i.
If arr1[i] and arr2[j] are not equal, then dp[i][j] = max(dp[i][l]) where 0 ? l < j.
Once we have computed the dp matrix, we can find the LCIS by backtracking from the maximum value in the matrix and following the same conditions as above.

Algorithm

1. Initialize the dp matrix of size (len(arr1)+1) x (len(arr2)+1) with zeros.
2. Initialize the max_lcis_length to 0.
3. Initialize the max_lcis_index to None.
4. Iterate through each element of arr1 and arr2.
5. If arr1[i] and arr2[j] are equal, then dp[i+1][j+1] = 1 + max(dp[k+1][l+1]) where 0 ? k < i and 0 ? l < j.
6. If arr1[i] and arr2[j] are not equal, then dp[i+1][j+1] = max(dp[k+1][j+1]) where 0 ? k < i.
7. If arr1[i] and arr2[j] are not equal, then dp[i+1][j+1] = max(dp[i+1][l+1]) where 0 ? l < j.
8. If dp[i+1][j+1] > max_lcis_length, then set max_lcis_length to dp[i+1][j+1] and max_lcis_index to (i, j).
9. Backtrack from the max_lcis_index to find the LCIS by following the same conditions as above.
10. Return the LCIS and its length.

C++




#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_set>
 
using namespace std;
 
// Function to generate all combinations of length 'k' for a list
void generateCombinations(vector<int>& arr, int k, int startIndex, vector<int>& current, vector<vector<int>>& combinations) {
    if (k == 0) {
        combinations.push_back(current);
        return;
    }
 
    for (int i = startIndex; i < arr.size(); i++) {
        current.push_back(arr[i]);
        generateCombinations(arr, k - 1, i + 1, current, combinations);
        current.pop_back();
    }
}
 
// Function to check if a vector is sorted
bool isSorted(const vector<int>& arr) {
    vector<int> sortedArr = arr;
    sort(sortedArr.begin(), sortedArr.end());
    return arr == sortedArr;
}
 
// Function to check if two vectors have the same elements
bool hasSameElements(const vector<int>& arr1, const vector<int>& arr2) {
    unordered_set<int> set1(arr1.begin(), arr1.end());
    unordered_set<int> set2(arr2.begin(), arr2.end());
    return set1 == set2;
}
 
// Function to find the Longest Common Increasing Subsequence
vector<int> lcis(vector<int>& arr1, vector<int>& arr2) {
    vector<int> lcis;
    int lcisLength = 0;
 
    // Iterate over possible lengths of LCIS
    for (int i = 1; i <= min(arr1.size(), arr2.size()); i++) {
        // Generate all combinations of length 'i' for arr1
        vector<int> emptyVec;  // Create an empty vector
        vector<vector<int>> combinations1;
        generateCombinations(arr1, i, 0, emptyVec, combinations1);
        for (const vector<int>& seq1 : combinations1) {
            // Check if the sequence is sorted
            if (!isSorted(seq1)) {
                continue;
            }
 
            // Generate all combinations of length 'i' for arr2
            vector<vector<int>> combinations2;
            generateCombinations(arr2, i, 0, emptyVec, combinations2);
            for (const vector<int>& seq2 : combinations2) {
                // Check if the sequence is sorted
                if (!isSorted(seq2)) {
                    continue;
                }
 
                // Check if the sequences have the same elements
                if (hasSameElements(seq1, seq2)) {
                    lcisLength = i;
                    lcis = seq1;
                }
            }
        }
    }
 
    return lcis;
}
 
int main() {
    vector<int> arr1 = {3, 4, 9, 1};
    vector<int> arr2 = {5, 3, 8, 9, 10, 2, 1};
 
    vector<int> result = lcis(arr1, arr2);
 
    cout << "Longest Common Increasing Subsequence: ";
    for (int num : result) {
        cout << num << " ";
    }
    cout << endl;
    cout << "Length of LCIS: " << result.size() << endl;
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Arrays;
import java.util.Collections;
 
public class LCIS {
     
    // Function to find the Longest Common Increasing Subsequence
    public static List<Integer> lcis(List<Integer> arr1, List<Integer> arr2) {
        List<Integer> lcis = new ArrayList<>();
        int lcisLength = 0;
         
        // Iterate over possible lengths of LCIS
        for (int i = 1; i <= Math.min(arr1.size(), arr2.size()); i++) {
            // Generate all combinations of length 'i' for arr1
            List<List<Integer>> combinations1 = generateCombinations(arr1, i);
            for (List<Integer> seq1 : combinations1) {
                // Check if the sequence is sorted
                if (!isSorted(seq1)) {
                    continue;
                }
                 
                // Generate all combinations of length 'i' for arr2
                List<List<Integer>> combinations2 = generateCombinations(arr2, i);
                for (List<Integer> seq2 : combinations2) {
                    // Check if the sequence is sorted
                    if (!isSorted(seq2)) {
                        continue;
                    }
                     
                    // Check if the sequences have the same elements
                    if (hasSameElements(seq1, seq2)) {
                        lcisLength = i;
                        lcis = seq1;
                    }
                }
            }
        }
         
        return lcis;
    }
     
    // Function to generate all combinations of length 'k' for a list
    public static List<List<Integer>> generateCombinations(List<Integer> arr, int k) {
        List<List<Integer>> combinations = new ArrayList<>();
        generateCombinationsHelper(arr, k, 0, new ArrayList<>(), combinations);
        return combinations;
    }
     
    // Helper function for generating combinations
    public static void generateCombinationsHelper(List<Integer> arr, int k, int startIndex, List<Integer> current, List<List<Integer>> combinations) {
        if (k == 0) {
            combinations.add(new ArrayList<>(current));
            return;
        }
         
        for (int i = startIndex; i < arr.size(); i++) {
            current.add(arr.get(i));
            generateCombinationsHelper(arr, k - 1, i + 1, current, combinations);
            current.remove(current.size() - 1);
        }
    }
     
    // Function to check if a list is sorted
    public static boolean isSorted(List<Integer> arr) {
        List<Integer> sortedArr = new ArrayList<>(arr);
        Collections.sort(sortedArr);
        return arr.equals(sortedArr);
    }
     
    // Function to check if two lists have the same elements
    public static boolean hasSameElements(List<Integer> arr1, List<Integer> arr2) {
        Set<Integer> set1 = new HashSet<>(arr1);
        Set<Integer> set2 = new HashSet<>(arr2);
        return set1.equals(set2);
    }
     
    public static void main(String[] args) {
        List<Integer> arr1 = Arrays.asList(3, 4, 9, 1);
        List<Integer> arr2 = Arrays.asList(5, 3, 8, 9, 10, 2, 1);
         
        List<Integer> result = lcis(arr1, arr2);
         
        System.out.println("Longest Common Increasing Subsequence: " + result);
        System.out.println("Length of LCIS: " + result.size());
    }
}


Python3




import itertools
 
def lcis(arr1, arr2):
    lcis = []
    lcis_length = 0
    for i in range(1, min(len(arr1), len(arr2)) + 1):
        for seq1 in itertools.combinations(arr1, i):
            if seq1 != tuple(sorted(seq1)):
                continue
            for seq2 in itertools.combinations(arr2, i):
                if seq2 != tuple(sorted(seq2)):
                    continue
                if set(seq1) == set(seq2):
                    lcis_length = i
                    lcis = seq1
    return lcis_length
arr1 = [3, 4, 9, 1]
arr2 = [5, 3, 8, 9, 10, 2, 1]
print(lcis(arr1, arr2))


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class Program
{
    static void Main()
    {
        int[] arr1 = { 3, 4, 9, 1 };
        int[] arr2 = { 5, 3, 8, 9, 10, 2, 1 };
 
        List<int> result = LCIS(arr1, arr2);
 
        Console.Write("Longest Common Increasing Subsequence: ");
        foreach (int num in result)
        {
            Console.Write(num + " ");
        }
        Console.WriteLine();
        Console.WriteLine("Length of LCIS: " + result.Count);
    }
 
    // Function to find the Longest Common Increasing Subsequence (LCIS)
    static List<int> LCIS(int[] arr1, int[] arr2)
    {
        List<int> lcis = new List<int>();
 
        // Iterate over possible lengths of LCIS
        for (int i = 1; i <= Math.Min(arr1.Length, arr2.Length); i++)
        {
            // Generate all combinations of length 'i' for arr1
            List<List<int>> combinations1 = GenerateCombinations(arr1, i);
            foreach (List<int> seq1 in combinations1)
            {
                // Check if the sequence is sorted
                if (!IsSorted(seq1))
                {
                    continue;
                }
 
                // Generate all combinations of length 'i' for arr2
                List<List<int>> combinations2 = GenerateCombinations(arr2, i);
                foreach (List<int> seq2 in combinations2)
                {
                    // Check if the sequence is sorted
                    if (!IsSorted(seq2))
                    {
                        continue;
                    }
 
                    // Check if the sequences have the same elements
                    if (HasSameElements(seq1, seq2))
                    {
                        lcis = new List<int>(seq1);
                    }
                }
            }
        }
 
        return lcis;
    }
 
    // Function to generate all combinations of length 'k' for an array
    static List<List<int>> GenerateCombinations(int[] arr, int k)
    {
        List<List<int>> combinations = new List<List<int>>();
        GenerateCombinationsHelper(arr, k, 0, new List<int>(), combinations);
        return combinations;
    }
 
    // Helper function to generate combinations
    static void GenerateCombinationsHelper(int[] arr, int k, int startIndex, List<int> current, List<List<int>> combinations)
    {
        if (k == 0)
        {
            combinations.Add(new List<int>(current));
            return;
        }
 
        for (int i = startIndex; i < arr.Length; i++)
        {
            current.Add(arr[i]);
            GenerateCombinationsHelper(arr, k - 1, i + 1, current, combinations);
            current.RemoveAt(current.Count - 1);
        }
    }
 
    // Function to check if a list is sorted
    static bool IsSorted(List<int> arr)
    {
        List<int> sortedArr = new List<int>(arr);
        sortedArr.Sort();
        return arr.SequenceEqual(sortedArr);
    }
 
    // Function to check if two lists have the same elements
    static bool HasSameElements(List<int> arr1, List<int> arr2)
    {
        HashSet<int> set1 = new HashSet<int>(arr1);
        HashSet<int> set2 = new HashSet<int>(arr2);
        return set1.SetEquals(set2);
    }
}


Javascript




// Function to generate all combinations of length 'k' for a list
function generateCombinations(arr, k, startIndex, current, combinations) {
    if (k === 0) {
        combinations.push([...current]);
        return;
    }
 
    for (let i = startIndex; i < arr.length; i++) {
        current.push(arr[i]);
        generateCombinations(arr, k - 1, i + 1, current, combinations);
        current.pop();
    }
}
 
// Function to check if an array is sorted
function isSorted(arr) {
    const sortedArr = [...arr];
    sortedArr.sort((a, b) => a - b);
    return JSON.stringify(arr) === JSON.stringify(sortedArr);
}
 
// Function to check if two arrays have the same elements
function hasSameElements(arr1, arr2) {
    const set1 = new Set(arr1);
    const set2 = new Set(arr2);
    return JSON.stringify([...set1]) === JSON.stringify([...set2]);
}
 
// Function to find the Longest Common Increasing Subsequence
function lcis(arr1, arr2) {
    let lcisArr = [];
    let lcisLength = 0;
 
    // Iterate over possible lengths of LCIS
    for (let i = 1; i <= Math.min(arr1.length, arr2.length); i++) {
        // Generate all combinations of length 'i' for arr1
        const emptyArray = [];
        const combinations1 = [];
        generateCombinations(arr1, i, 0, emptyArray, combinations1);
 
        for (const seq1 of combinations1) {
            // Check if the sequence is sorted
            if (!isSorted(seq1)) {
                continue;
            }
 
            // Generate all combinations of length 'i' for arr2
            const combinations2 = [];
            generateCombinations(arr2, i, 0, emptyArray, combinations2);
 
            for (const seq2 of combinations2) {
                // Check if the sequence is sorted
                if (!isSorted(seq2)) {
                    continue;
                }
 
                // Check if the sequences have the same elements
                if (hasSameElements(seq1, seq2)) {
                    lcisLength = i;
                    lcisArr = [...seq1];
                }
            }
        }
    }
 
    return lcisArr;
}
 
const arr1 = [3, 4, 9, 1];
const arr2 = [5, 3, 8, 9, 10, 2, 1];
 
const result = lcis(arr1, arr2);
 
console.log("Length of LCIS: " + result.length);
// This code is contributed by Taranpreet Singh.


Output

2







Time Complexity: O(n^4) where n is the length of the longer array. This is because we are computing the dp matrix by iterating through each element of arr1 and arr2 and then iterating through all possible pairs of indices (k,l) and (i,j). Backtracking from the max_lcis_index takes O(n) time.
Space Complexity: O(n^2) as we are using a matrix of size (len(arr1)+1) x (len(arr2)+1) to store the LCIS of two arrays.

This article is contributed Rachit Belwariar.



Last Updated : 07 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads