Given two arrays firstArr[], consisting of distinct elements only, and secondArr[], the task is to find the length of LCS between these 2 arrays.
Examples:
Input: firstArr[] = {3, 5, 1, 8}, secondArr[] = {3, 3, 5, 3, 8}
Output: 3.
Explanation: LCS between these two arrays is {3, 5, 8}.
Input : firstArr[] = {1, 2, 1}, secondArr[] = {3}
Output: 0
Naive Approach: Follow the steps below to solve the problem using the simplest possible approach:
- Initialize an array dp[][] such that dp[i][j] stores longest common subsequence of firstArr[ :i] and secondArr[ :j].
- Traverse the array firstArr[] and for every array element of the array firstArr[], traverse the array secondArr[].
- If firstArr[i] = secondArr[j]: Set dp[i][j] = dp[i – 1][j – 1] + 1.
- Otherwise: Set dp[i][j] = max(dp[ i – 1][j], dp[i][j – 1]).
Time Complexity: O(N * M), where N and M are the sizes of the arrays firstArr[] and secondArr[] respectively.
Auxiliary Space: O(N * M)
Efficient Approach: To optimize the above approach, follow the steps below:
- Initialize a Map, say mp, to store the mappings map[firstArr[i]] = i, i.e. map elements of the first array to their respective indices.
- Since the elements which are present in secondArr[] but not in the firstArr[] are not useful at all, as they can never be a part of a common subsequence, traverse the array secondArr[] andfor each array element, check if it is present in the Map or not.
- If found to be true, push map[secondArr[i]] into a temporary Array. Otherwise ignore it.
- Find the Longest Increasing Subsequence (LIS) of the obtained temporary array and print its length as the required answer.
Illustration:
firstArr[] = {3, 5, 1, 8}
secondArr={3, 3, 4, 5, 3, 8}
Mapping: 3->0, 5->1, 1->2, 8->3 (From firstArr)
tempArr[] = {0, 0, 1, 0, 3}
Therefore, length of LIS of tempArr[] = 3 ({0, 1, 3})
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int LCS(vector< int >& firstArr,
vector< int >& secondArr)
{
unordered_map< int , int > mp;
for ( int i = 0; i < firstArr.size(); i++) {
mp[firstArr[i]] = i + 1;
}
vector< int > tempArr;
for ( int i = 0; i < secondArr.size(); i++) {
if (mp.find(secondArr[i]) != mp.end()) {
tempArr.push_back(mp[secondArr[i]]);
}
}
vector< int > tail;
tail.push_back(tempArr[0]);
for ( int i = 1; i < tempArr.size(); i++) {
if (tempArr[i] > tail.back())
tail.push_back(tempArr[i]);
else if (tempArr[i] < tail[0])
tail[0] = tempArr[i];
else {
auto it = lower_bound(tail.begin(),
tail.end(),
tempArr[i]);
*it = tempArr[i];
}
}
return ( int )tail.size();
}
int main()
{
vector< int > firstArr = { 3, 5, 1, 8 };
vector< int > secondArr = { 3, 3, 5, 3, 8 };
cout << LCS(firstArr, secondArr);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int LCS( int [] firstArr, int [] secondArr)
{
HashMap<Integer,Integer> mp = new HashMap<Integer,Integer>();
for ( int i = 0 ; i < firstArr.length; i++)
{
mp.put(firstArr[i], i + 1 );
}
Vector<Integer> tempArr = new Vector<>();
for ( int i = 0 ; i < secondArr.length; i++)
{
if (mp.containsKey(secondArr[i]))
{
tempArr.add(mp.get(secondArr[i]));
}
}
Vector<Integer> tail = new Vector<>();
tail.add(tempArr.get( 0 ));
for ( int i = 1 ; i < tempArr.size(); i++)
{
if (tempArr.get(i) > tail.lastElement())
tail.add(tempArr.get(i));
else if (tempArr.get(i) < tail.get( 0 ))
tail.add( 0 , tempArr.get(i));
}
return ( int )tail.size();
}
public static void main(String[] args)
{
int [] firstArr = { 3 , 5 , 1 , 8 };
int [] secondArr = { 3 , 3 , 5 , 3 , 8 };
System.out.print(LCS(firstArr, secondArr));
}
}
|
Python3
from bisect import bisect_left
def LCS(firstArr, secondArr):
mp = {}
for i in range ( len (firstArr)):
mp[firstArr[i]] = i + 1
tempArr = []
for i in range ( len (secondArr)):
if (secondArr[i] in mp):
tempArr.append(mp[secondArr[i]])
tail = []
tail.append(tempArr[ 0 ])
for i in range ( 1 , len (tempArr)):
if (tempArr[i] > tail[ - 1 ]):
tail.append(tempArr[i])
elif (tempArr[i] < tail[ 0 ]):
tail[ 0 ] = tempArr[i]
else :
it = bisect_left(tail, tempArr[i])
it = tempArr[i]
return len (tail)
if __name__ = = '__main__' :
firstArr = [ 3 , 5 , 1 , 8 ]
secondArr = [ 3 , 3 , 5 , 3 , 8 ]
print (LCS(firstArr, secondArr))
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
static int LCS( int [] firstArr, int [] secondArr)
{
Dictionary< int , int > mp = new Dictionary< int , int >();
for ( int i = 0; i < firstArr.Length; i++)
{
mp.Add(firstArr[i], i + 1);
}
List< int > tempArr = new List< int >();
for ( int i = 0; i < secondArr.Length; i++)
{
if (mp.ContainsKey(secondArr[i]))
{
tempArr.Add(mp[secondArr[i]]);
}
}
List< int > tail = new List< int >();
tail.Add(tempArr[0]);
for ( int i = 1; i < tempArr.Count; i++)
{
if (tempArr[i] > tail[tail.Count-1])
tail.Add(tempArr[i]);
else if (tempArr[i] < tail[0])
tail.Insert(0, tempArr[i]);
}
return ( int )tail.Count;
}
public static void Main(String[] args)
{
int [] firstArr = { 3, 5, 1, 8 };
int [] secondArr = { 3, 3, 5, 3, 8 };
Console.Write(LCS(firstArr, secondArr));
}
}
|
Javascript
<script>
function LCS(firstArr, secondArr)
{
let mp = new Map()
for (let i = 0; i < firstArr.length; i++)
{
mp.set(firstArr[i], i + 1);
}
let tempArr = [];
for (let i = 0; i < secondArr.length; i++)
{
if (mp.has(secondArr[i]))
{
tempArr.push(mp.get(secondArr[i]));
}
}
let tail = [];
tail.push(tempArr[0]);
for (let i = 1; i < tempArr.length; i++)
{
if (tempArr[i] > tail[tail.length - 1])
tail.push(tempArr[i]);
else if (tempArr[i] < tail[0])
tail.unshift(0, tempArr[i]);
}
return tail.length;
}
let firstArr = [ 3, 5, 1, 8 ];
let secondArr = [ 3, 3, 5, 3, 8 ];
document.write(LCS(firstArr, secondArr));
</script>
|
Time Complexity: O(NlogN)
Auxiliary Space: O(N)