给定两个仅由不同元素组成的数组firstArr[]和secondArr[] ,任务是找到这两个数组之间的 LCS 长度。
例子:
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
朴素的方法:按照以下步骤使用最简单的方法解决问题:
- 初始化一个数组dp[][]使得dp[i][j]存储firstArr[ :i]和secondArr[ :j] 的最长公共子序列。
- 遍历数组firstArr []和用于阵列firstArr []的每个数组元素,遍历数组secondArr []。
- 如果 firstArr[i] = secondArr[j]:设置dp[i][j] = dp[i – 1][j – 1] + 1 。
- 否则:设置dp[i][j] = max(dp[ i – 1][j], dp[i][j – 1]) 。
时间复杂度: O(N * M),其中 N 和 M 分别是数组 firstArr[] 和 secondArr[] 的大小。
辅助空间: O(N * M)
高效的方法:要优化上述方法,请按照以下步骤操作:
- 初始化一个 Map,比如mp ,以存储映射map[firstArr[i]] = i ,即将第一个数组的元素映射到它们各自的索引。
- 由于存在于secondArr[]但不在firstArr[] 中的元素根本没有用,因为它们永远不会成为公共子序列的一部分,因此遍历数组secondArr[] 并对于每个数组元素,检查它是否是是否出现在地图中。
- 如果发现为真,则将 map[secondArr[i]]推入一个临时数组。否则忽略它。
- 找到获得的临时数组的最长递增子序列(LIS),并将其长度打印为所需答案。
插图:
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})
下面是上述方法的实现:
C++
// C++ program to to implement
// the above approach
#include
using namespace std;
// Function to find the Longest Common
// Subsequence between the two arrays
int LCS(vector& firstArr,
vector& secondArr)
{
// Maps elements of firstArr[]
// to their respective indices
unordered_map mp;
// Traverse the array firstArr[]
for (int i = 0; i < firstArr.size(); i++) {
mp[firstArr[i]] = i + 1;
}
// Stores the indices of common elements
// between firstArr[] and secondArr[]
vector tempArr;
// Traverse the array secondArr[]
for (int i = 0; i < secondArr.size(); i++) {
// If current element exists in the Map
if (mp.find(secondArr[i]) != mp.end()) {
tempArr.push_back(mp[secondArr[i]]);
}
}
// Stores lIS from tempArr[]
vector 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();
}
// Driver Code
int main()
{
vector firstArr = { 3, 5, 1, 8 };
vector secondArr = { 3, 3, 5, 3, 8 };
cout << LCS(firstArr, secondArr);
return 0;
}
Java
// Java program to to implement
// the above approach
import java.util.*;
class GFG
{
// Function to find the Longest Common
// Subsequence between the two arrays
static int LCS(int[] firstArr,int[] secondArr)
{
// Maps elements of firstArr[]
// to their respective indices
HashMap mp = new HashMap();
// Traverse the array firstArr[]
for (int i = 0; i < firstArr.length; i++)
{
mp.put(firstArr[i], i + 1);
}
// Stores the indices of common elements
// between firstArr[] and secondArr[]
Vector tempArr = new Vector<>();
// Traverse the array secondArr[]
for (int i = 0; i < secondArr.length; i++)
{
// If current element exists in the Map
if (mp.containsKey(secondArr[i]))
{
tempArr.add(mp.get(secondArr[i]));
}
}
// Stores lIS from tempArr[]
Vector 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();
}
// Driver Code
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));
}
}
// This code is contributed by gauravrajput1
Python3
# Python3 program to to implement
# the above approach
from bisect import bisect_left
# Function to find the Longest Common
# Subsequence between the two arrays
def LCS(firstArr, secondArr):
# Maps elements of firstArr[]
# to their respective indices
mp = {}
# Traverse the array firstArr[]
for i in range(len(firstArr)):
mp[firstArr[i]] = i + 1
# Stores the indices of common elements
# between firstArr[] and secondArr[]
tempArr = []
# Traverse the array secondArr[]
for i in range(len(secondArr)):
# If current element exists in the Map
if (secondArr[i] in mp):
tempArr.append(mp[secondArr[i]])
# Stores lIS from tempArr[]
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)
# Driver Code
if __name__ == '__main__':
firstArr = [3, 5, 1, 8 ]
secondArr = [3, 3, 5, 3, 8 ]
print (LCS(firstArr, secondArr))
# This code is contributed by mohit kumar 29
C#
// C# program to to implement
// the above approach
using System;
using System.Collections.Generic;
public class GFG
{
// Function to find the longest Common
// Subsequence between the two arrays
static int LCS(int[] firstArr,int[] secondArr)
{
// Maps elements of firstArr[]
// to their respective indices
Dictionary mp = new Dictionary();
// Traverse the array firstArr[]
for (int i = 0; i < firstArr.Length; i++)
{
mp.Add(firstArr[i], i + 1);
}
// Stores the indices of common elements
// between firstArr[] and secondArr[]
List tempArr = new List();
// Traverse the array secondArr[]
for (int i = 0; i < secondArr.Length; i++)
{
// If current element exists in the Map
if (mp.ContainsKey(secondArr[i]))
{
tempArr.Add(mp[secondArr[i]]);
}
}
// Stores lIS from tempArr[]
List tail = new List();
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;
}
// Driver Code
public static void Main(String[] args)
{
int[] firstArr = { 3, 5, 1, 8 };
int[] secondArr = { 3, 3, 5, 3, 8 };
Console.Write(LCS(firstArr, secondArr));
}
}
// This code is contributed by Rajput-Ji.
Javascript
3
时间复杂度: O(NlogN)
辅助空间: O(N)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。