📌  相关文章
📜  两个数组的最长公共子序列,其中一个数组仅由不同的元素组成

📅  最后修改于: 2021-04-29 09:33:01             🧑  作者: Mango

给定两个仅由不同元素组成的数组firstArr []secondArr [] ,任务是找到这两个数组之间LCS的长度。

例子:

天真的方法:按照以下步骤使用最简单的方法解决问题:

  • 初始化数组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)

高效方法:要优化上述方法,请按照以下步骤操作:

  • 初始化一个映射,例如mp ,以存储映射map [firstArr [i]] = i ,即将第一个数组的映射元素映射到它们各自的索引。
  • 由于存在于secondArr []中但不存在于firstArr []中的元素根本没有用,因为它们永远不可能成为公共子序列的一部分,因此遍历数组secondArr []并针对每个数组元素检查其是否为是否存在于地图中
  • 如果发现为真,则将map [secondArr [i]]推送到临时Array中。否则忽略它。
  • 找到获得的临时数组的最长递增子序列(LIS),并打印其长度作为所需答案。

插图:

下面是上述方法的实现:

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.


输出:
3

时间复杂度: O(NlogN)
辅助空间: O(N)