Open In App

Minimize insertions and deletions in given array A[] to make it identical to array B[]

Improve
Improve
Like Article
Like
Save
Share
Report

Given two arrays A[] and B[] of length N and M respectively, the task is to find the minimum number of insertions and deletions on the array A[], required to make both the arrays identical.
Note: Array B[] is sorted and all its elements are distinct, operations can be performed at any index not necessarily at the end.

Example:

Input: A[] = {1, 2, 5, 3, 1}, B[] = {1, 3, 5}
Output:
Explanation: In 1st operation, delete A[1] from array A[] and in 2nd operation, insert 3 at that position. In 3rd and 4th operation, delete A[3] and A[4]. Hence, A[] = {1, 3, 5} = B[] in 4 operations which is the minimum possible.

Input: A[] = {1, 4}, B[] = {1, 4}
Output: 0

 

Approach: The given problem can be solved by observing the fact that the most optimal choice of elements that must not be deleted from the array A[] are the elements of the Longest Increasing Subsequence among the common elements in A[] and B[]. Therefore, the above problem can be solved by storing the common elements of the array A[] and B[] in a vector and finding the LIS using this algorithm. Thereafter, all the elements other than that of LIS can be deleted from A[], and the remaining elements that are in B[] but not in A[] can be inserted.

Below is the implementation of the above approach:

C++




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find minimum operations
// to convert array A to B using
// insertions and deletion opertations
int minInsAndDel(int A[], int B[], int n, int m)
{
 
    // Stores the common elements in A and B
    vector<int> common;
    unordered_set<int> s;
 
    // Loop to iterate over B
    for (int i = 0; i < m; i++) {
        s.insert(B[i]);
    }
 
    // Loop to iterate over A
    for (int i = 0; i < n; i++) {
 
        // If current element is also present
        // in array B
        if (s.find(A[i]) != s.end()) {
            common.push_back(A[i]);
        }
    }
 
    // Stores the Longest Increasing Subsequence
    // among the common elements in A and B
    vector<int> lis;
 
    // Loop to find the LIS among the common
    // elements in A and B
    for (auto e : common) {
        auto it = lower_bound(
            lis.begin(), lis.end(), e);
 
        if (it != lis.end())
            *it = e;
        else
            lis.push_back(e);
    }
 
    // Stores the final answer
    int ans;
 
    // Count of elements to be inserted in A[]
    ans = m - lis.size();
 
    // Count of elements to be deleted from A[]
    ans += n - lis.size();
 
    // Return Answer
    return ans;
}
 
// Driver Code
int main()
{
    int N = 5, M = 3;
    int A[] = { 1, 2, 5, 3, 1 };
    int B[] = { 1, 3, 5 };
 
    cout << minInsAndDel(A, B, N, M) << endl;
 
    return 0;
}


Java




/*package whatever //do not write package name here */
import java.util.*;
 
class GFG
{
   
  // Function to implement lower_bound
static int lower_bound(int arr[], int X)
{
    int mid;
    int N = arr.length;
   
    // Initialise starting index and
    // ending index
    int low = 0;
    int high = N;
  
    // Till low is less than high
    while (low < high) {
        mid = low + (high - low) / 2;
  
        // If X is less than or equal
        // to arr[mid], then find in
        // left subarray
        if (X <= arr[mid]) {
            high = mid;
        }
  
        // If X is greater arr[mid]
        // then find in right subarray
        else {
            low = mid + 1;
        }
    }
    
    // if X is greater than arr[n-1]
    if(low < N && arr[low] < X) {
       low++;
    }
        
    // Return the lower_bound index
    return low;
}
  
    // Function to find minimum operations
    // to convert array A to B using
    // insertions and deletion opertations
    static int minInsAndDel(int A[], int B[], int n, int m)
    {
 
        // Stores the common elements in A and B
        int[] common = new int[n];
        int k = 0;
        HashSet<Integer> s= new HashSet<Integer>();
 
        // Loop to iterate over B
        for (int i = 0; i < m; i++) {
            s.add(B[i]);
        }
 
        // Loop to iterate over A
        for (int i = 0; i < n; i++) {
 
            // If current element is also present
            // in array B
            if (s.contains(A[i]) == false) {
                common[k++] = A[i];
            }
        }
 
        // Stores the Longest Increasing Subsequence
        // among the common elements in A and B
        int[] lis = new int[n];
        k = 0;
      ArrayList<Integer> LIS = new ArrayList<Integer>();
       
        // Loop to find the LIS among the common
        // elements in A and B
        for (int e : common) {
            int it = lower_bound(lis, e);
 
            if (it <lis.length)
                it = e;
            else{
                lis[k++] = e;
                LIS.add(e);
            }
        }
 
        // Stores the final answer
        int ans;
 
        // Count of elements to be inserted in A[]
        ans = m - LIS.size()-1;
 
        // Count of elements to be deleted from A[]
        ans = ans+ n - LIS.size()-1;
 
        // Return Answer
        return ans;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int N = 5, M = 3;
        int A[] = { 1, 2, 5, 3, 1 };
        int B[] = { 1, 3, 5 };
 
        System.out.println(minInsAndDel(A, B, N, M));
    }
}
 
// This code is contributed by lokeshpotta20.


Python3




# python program of the above approach
from bisect import bisect_left
 
# Function to find minimum operations
# to convert array A to B using
# insertions and deletion opertations
def minInsAndDel(A, B, n, m):
 
    # Stores the common elements in A and B
    common = []
    s = set()
 
    # Loop to iterate over B
    for i in range(0, m):
        s.add(B[i])
 
    # Loop to iterate over A
    for i in range(0, n):
 
        # If current element is also present
        # in array B
        if (A[i] in s):
            common.append(A[i])
 
    # Stores the Longest Increasing Subsequence
    # among the common elements in A and B
    lis = []
 
    # Loop to find the LIS among the common
    # elements in A and B
    for e in common:
        it = bisect_left(lis, e, 0, len(lis))
 
        if (it != len(lis)):
            lis[it] = e
        else:
            lis.append(e)
 
    # Stores the final answer
    ans = 0
 
    # Count of elements to be inserted in A[]
    ans = m - len(lis)
 
    # Count of elements to be deleted from A[]
    ans += n - len(lis)
 
    # Return Answer
    return ans
 
# Driver Code
if __name__ == "__main__":
 
    N = 5
    M = 3
    A = [1, 2, 5, 3, 1]
    B = [1, 3, 5]
 
    print(minInsAndDel(A, B, N, M))
 
    # This code is contributed by rakeshsahni


C#




/*package whatever //do not write package name here */
using System;
using System.Collections.Generic;
 
class GFG {
 
    // Function to implement lower_bound
    static int lower_bound(int[] arr, int X)
    {
        int mid;
        int N = arr.Length;
 
        // Initialise starting index and
        // ending index
        int low = 0;
        int high = N;
 
        // Till low is less than high
        while (low < high) {
            mid = low + (high - low) / 2;
 
            // If X is less than or equal
            // to arr[mid], then find in
            // left subarray
            if (X <= arr[mid]) {
                high = mid;
            }
 
            // If X is greater arr[mid]
            // then find in right subarray
            else {
                low = mid + 1;
            }
        }
 
        // if X is greater than arr[n-1]
        if (low < N && arr[low] < X) {
            low++;
        }
 
        // Return the lower_bound index
        return low;
    }
 
    // Function to find minimum operations
    // to convert array A to B using
    // insertions and deletion opertations
    static int minInsAndDel(int[] A, int[] B, int n, int m)
    {
 
        // Stores the common elements in A and B
        int[] common = new int[n];
        int k = 0;
        HashSet<int> s = new HashSet<int>();
 
        // Loop to iterate over B
        for (int i = 0; i < m; i++) {
            s.Add(B[i]);
        }
 
        // Loop to iterate over A
        for (int i = 0; i < n; i++) {
 
            // If current element is also present
            // in array B
            if (s.Contains(A[i]) == false) {
                common[k++] = A[i];
            }
        }
 
        // Stores the Longest Increasing Subsequence
        // among the common elements in A and B
        int[] lis = new int[n];
        k = 0;
        List<int> LIS = new List<int>();
 
        // Loop to find the LIS among the common
        // elements in A and B
        foreach(int e in common)
        {
            int it = lower_bound(lis, e);
 
            if (it < lis.Length)
                it = e;
            else {
                lis[k++] = e;
                LIS.Add(e);
            }
        }
 
        // Stores the final answer
        int ans;
 
        // Count of elements to be inserted in A[]
        ans = m - LIS.Count - 1;
 
        // Count of elements to be deleted from A[]
        ans = ans + n - LIS.Count - 1;
 
        // Return Answer
        return ans;
    }
 
    // Driver Code
    public static void Main(string[] args)
    {
        int N = 5, M = 3;
        int[] A = { 1, 2, 5, 3, 1 };
        int[] B = { 1, 3, 5 };
 
        Console.WriteLine(minInsAndDel(A, B, N, M));
    }
}
 
// This code is contributed by ukasp.


Javascript




<script>
// Javascript program of the above approach
 
// Function to find minimum operations
// to convert array A to B using
// insertions and deletion opertations
function minInsAndDel(A, B, n, m) {
 
  // Stores the common elements in A and B
  let common = [];
  let s = new Set();
 
  // Loop to iterate over B
  for (let i = 0; i < m; i++) {
    s.add(B[i]);
  }
 
  // Loop to iterate over A
  for (let i = 0; i < n; i++) {
 
    // If current element is also present
    // in array B
    if (s.has(A[i])) {
      common.push(A[i]);
    }
  }
 
  // Stores the Longest Increasing Subsequence
  // among the common elements in A and B
  let lis = [];
 
  // Loop to find the LIS among the common
  // elements in A and B
  for (e of common) {
    let it = lower_bound(lis, lis.length, e);
 
    if (lis.includes(it))
      it = e;
    else
      lis.push(e);
  }
 
  // Stores the final answer
  let ans;
 
  // Count of elements to be inserted in A[]
  ans = m - lis.length;
 
  // Count of elements to be deleted from A[]
  ans += n - lis.length;
 
  // Return Answer
  return ans;
}
 
 
function lower_bound(arr, N, X)
{
    let mid;
 
    // Initialise starting index and
    // ending index
    let low = 0;
    let high = N;
 
  // Till low is less than high
  while (low < high) {
    mid = Math.floor(low + (high - low) / 2);
 
    // If X is less than or equal
    // to arr[mid], then find in
    // left subarray
    if (X <= arr[mid]) {
      high = mid;
    }
 
    // If X is greater arr[mid]
    // then find in right subarray
    else {
      low = mid + 1;
    }
  }
 
  // if X is greater than arr[n-1]
  if (low < N && arr[low] < X) {
    low++;
  }
 
  // Return the lower_bound index
  return low;
}
 
 
// Driver Code
let N = 5, M = 3;
let A = [1, 2, 5, 3, 1];
let B = [1, 3, 5];
 
document.write(minInsAndDel(A, B, N, M));
 
// This code is contributed by saurabh_jaiswal.
</script>


Output

4

Time Complexity: O(N*log N)
Auxiliary Space: O(N)

Another Approach:

  1. Find the common elements in arrays A and B:
    Traverse through arrays A and B, and for each element of A that is present in B, add it to a vector or list of common elements.
  2. Find the Longest Increasing Subsequence (LIS) among the common elements:
    Find the LIS of the common elements using any standard LIS algorithm, such as dynamic programming, binary search, or segment trees. The length of the LIS will give the number of elements in A that need to be retained to make it identical to B.
  3. Calculate the minimum number of insertions and deletions required:
    The minimum number of insertions and deletions required can be calculated as follows:                                                                                                   Number of deletions = length of A – length of LIS
    Number of insertions = length of B – length of LIS
    Total number of operations = Number of deletions + Number of insertions
  4. Return the answer:
    Return the total number of operations as the answer.

Below is the implementation of the above approach:

C++




// C++ program of the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find minimum operations
// to convert array A to B using
// insertions and deletion opertations
int minInsAndDel(int A[], int B[], int n, int m)
{
  // Stores the common elements in A and B
vector<int> common;
 
// Loop to iterate over B
for (int i = 0; i < m; i++) {
    if (binary_search(A, A + n, B[i])) {
        common.push_back(B[i]);
    }
}
 
// Stores the Longest Increasing Subsequence
// among the common elements in A and B
vector<int> lis;
 
// Loop to find the LIS among the common
// elements in A and B
for (auto e : common) {
    auto it = lower_bound(
        lis.begin(), lis.end(), e);
 
    if (it != lis.end())
        *it = e;
    else
        lis.push_back(e);
}
 
// Stores the final answer
int ans;
 
// Length of array A[] + Length of array B[]
int total = n + m;
 
// Length of LIS among A[] and B[]
int lis_length = lis.size();
 
// Minimum number of insertions and deletions
ans = total - 2 * lis_length;
 
// Return Answer
return ans;
  }
 
// Driver Code
int main()
{
int N = 5, M = 3;
int A[] = { 1, 2, 5, 3, 1 };
int B[] = { 1, 3, 5 };
  cout << minInsAndDel(A, B, N, M) << endl;
 
return 0;
}


Java




import java.util.*;
 
public class Main {
    // Function to find minimum operations
    // to convert array A to B using
    // insertions and deletion opertations
    static int minInsAndDel(int A[], int B[], int n, int m) {
        // Stores the common elements in A and B
        ArrayList<Integer> common = new ArrayList<Integer>();
 
        // Loop to iterate over B
        for (int i = 0; i < m; i++) {
            if (Arrays.binarySearch(A, B[i]) >= 0) {
                common.add(B[i]);
            }
        }
 
        // Stores the Longest Increasing Subsequence
        // among the common elements in A and B
        ArrayList<Integer> lis = new ArrayList<Integer>();
 
        // Loop to find the LIS among the common
        // elements in A and B
        for (int e : common) {
            int idx = Collections.binarySearch(lis, e);
            if (idx >= 0)
                lis.set(idx, e);
            else
                lis.add(-(idx + 1), e);
        }
 
        // Stores the final answer
        int ans;
 
        // Length of array A[] + Length of array B[]
        int total = n + m;
 
        // Length of LIS among A[] and B[]
        int lis_length = lis.size();
 
        // Minimum number of insertions and deletions
        ans = total - 2 * lis_length;
 
        // Return Answer
        return ans;
    }
 
    // Driver Code
    public static void main(String[] args) {
        int N = 5, M = 3;
        int A[] = { 1, 2, 5, 3, 1 };
        int B[] = { 1, 3, 5 };
        System.out.println(minInsAndDel(A, B, N, M));
    }
}


Python3




# Python3 program of the above approach
from typing import List
import bisect
 
def minInsAndDel(A: List[int], B: List[int], n: int, m: int) -> int:
    # Stores the common elements in A and B
    common = []
 
    # Loop to iterate over B
    for i in range(m):
        if B[i] in A:
            common.append(B[i])
 
    # Stores the Longest Increasing Subsequence among the common elements in A and B
    lis = []
 
    # Loop to find the LIS among the common elements in A and B
    for e in common:
        idx = bisect.bisect_right(lis, e)
        if idx < len(lis):
            lis[idx] = e
        else:
            lis.append(e)
 
    # Stores the final answer
    ans = 0
 
    # Length of array A[] + Length of array B[]
    total = n + m
 
    # Length of LIS among A[] and B[]
    lis_length = len(lis)
 
    # Minimum number of insertions and deletions
    ans = total - 2 * lis_length
 
    # Return Answer
    return ans
 
# Driver Code
N, M = 5, 3
A = [1, 2, 5, 3, 1]
B = [1, 3, 5]
print(minInsAndDel(A, B, N, M))


C#




// C# program of the above approach
using System;
using System.Collections.Generic;
using System.Linq;
 
public class Program
{
    // Function to find minimum operations
    // to convert array A to B using
    // insertions and deletion operations
    public static int MinInsAndDel(int[] A, int[] B, int n, int m)
    {
        // Stores the common elements in A and B
        List<int> common = new List<int>();
 
        // Loop to iterate over B
        for (int i = 0; i < m; i++)
        {
            if (Array.BinarySearch(A, B[i]) >= 0)
            {
                common.Add(B[i]);
            }
        }
 
        // Stores the Longest Increasing Subsequence
        // among the common elements in A and B
        List<int> lis = new List<int>();
 
        // Loop to find the LIS among the common
        // elements in A and B
        foreach (var e in common)
        {
            var index = lis.BinarySearch(e);
            if (index < 0)
            {
                lis.Insert(~index, e);
            }
        }
 
        // Stores the final answer
        int ans;
 
        // Length of array A[] + Length of array B[]
        int total = n + m;
 
        // Length of LIS among A[] and B[]
        int lis_length = lis.Count();
 
        // Minimum number of insertions and deletions
        ans = total - 2 * lis_length;
 
        // Return Answer
        return ans;
    }
 
    // Driver Code
    public static void Main()
    {
        int N = 5, M = 3;
        int[] A = { 1, 2, 5, 3, 1 };
        int[] B = { 1, 3, 5 };
        Console.WriteLine(MinInsAndDel(A, B, N, M));
    }
}


Javascript




// Function to find minimum operations
// to convert array A to B using
// insertions and deletion operations
function minInsAndDel(A, B, n, m) {
  // Stores the common elements in A and B
  let common = [];
 
  // Loop to iterate over B
  for (let i = 0; i < m; i++) {
    if (A.includes(B[i])) {
      common.push(B[i]);
    }
  }
 
  // Stores the Longest Increasing Subsequence
  // among the common elements in A and B
  let lis = [];
 
  // Loop to find the LIS among the common
  // elements in A and B
  for (let i = 0; i < common.length; i++) {
    let e = common[i];
    let index = lis.findIndex((x) => x === e);
    if (index === -1) {
      lis.splice(~index, 0, e);
    }
  }
 
  // Stores the final answer
  let ans;
 
  // Length of array A[] + Length of array B[]
  let total = n + m;
 
  // Length of LIS among A[] and B[]
  let lis_length = lis.length;
 
  // Minimum number of insertions and deletions
  ans = total - 2 * lis_length + Math.abs(n - m);
 
  // Return Answer
  return ans;
}
 
// Driver Code
let N = 5,
  M = 3;
let A = [1, 2, 5, 3, 1];
let B = [1, 3, 5];
console.log(minInsAndDel(A, B, N, M));
// akashish__


Output

4

Time Complexity: O(N*logN)

Auxiliary Space: O(N)



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