Open In App

Replace all occurrences of X by Y or add element K in Array for Q queries

Last Updated : 01 Jul, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Given an empty array A[] & Q queries of two types 1 and 2 represented by queries1 and queries2 respectively, the task is to find the final state of the array. The queries are of the following type:

  • If type[i]=1, insert queries1[i] (say K) to the end of the array A. The value of queries2[i] = -1 for this type of query.
  • If type[i]=2, replace all occurrences of queries1[i] (say X) with queries2[i] (say Y) in A[].

Examples:

Input: Q = 3, type = [1, 1, 2], queries1 = [1, 2, 1], queries2 = [-1, -1, 2]
Output: A = [2, 2]
Explanation: Initially A[] is empty. 
After 1st query, A = [1]. 
After 2nd query, A = [1, 2]. 
After 3rd query, A = [2, 2].

Input: Q = 5, type = [1, 1, 1, 2, 2], queries1 = [1, 2, 3, 1, 3], queries2 = [-1, -1, -1, 2, 1]
Output: A = [2, 2, 1]
Explanation: Initially A[] is empty. 
After 1st query, A = [1]. After 2nd query, A = [1, 2]. 
After 3rd query, A = [1, 2, 3]. 
After 4th query A = [2, 2, 3]. 
After 5th query, A = [2, 2, 1].

Input: Q=5, type = [1, 1, 1, 2, 2], queries1 = [1, 2, 3, 1, 2], queries2 = [-1, -1, -1, 2, 3]
Output: A = [3, 3, 3]
Explanation: Initially A[] is empty. 
After 1st query, A = [1]. After 2nd query, A = [1, 2]. 
After 3rd query, A = [1, 2, 3]. After 4th query, A = [2, 2, 3]. 
After 5th query, A = [3, 3, 3].

 

Naive Approach:

The basic way to solve the problem is to iterate through all the queries type, and for each type[i] = 1 add queries1[i] in A else if type[i]=2, find all occurrences of queries1[i] in A and replace it with queries2[i].

Time Complexity: O(Q2)
Auxiliary Space: O(1)

Efficient Approach: The problem can be solved efficiently using Hashing based on the following idea:

Use a map to store indices of the elements in the array. For  all queries of type 2, find the values to be replaced and give those indices to the replaced values.

Follow the steps below to implement the approach:

  • Iterate through each query types of types[i] = 1 (for insertion in A) and types[i] = 2 for replacement of queries1[i] with queries2[i] in A.
  • For all queries types[i] = 2, if queries1[i] is present in the hashmap, then copy the vector associated to it into queries2[i] and erase whole of queries1[i]. 
  • After all the queries are performed, copy all the values of the hashmap back into the original vector A, with use of indices stored in the hashmap (keys stored as elements and vectors associated that stores indices of that element).
  • Now the original vector A is updated and is the final state of the array

Below is the implementation for the above approach:

C++14




// C++ code to implement the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the final state of array
vector<int> processQ(int Q, vector<int> types,
                     vector<int> queries1,
                     vector<int> queries2)
{
    // Initializing an unordered map
    unordered_map<int, vector<int> > indices;
    int cnt = 0;
    for (int i = 0; i < Q; i++) {
        if (types[i] == 1) {
            indices[queries1[i]].push_back(cnt++);
        }
        else {
            for (auto& x : indices[queries1[i]])
                indices[queries2[i]].push_back(x);
            indices[queries1[i]].clear();
        }
    }
 
    vector<int> A(cnt);
    for (auto& x : indices) {
        for (auto& y : x.second)
            A[y] = x.first;
    }
 
    return A;
}
 
// Driver code
int main()
{
    vector<int> types = { 1, 1, 2 };
    vector<int> queries1 = { 1, 2, 1 };
    vector<int> queries2 = { -1, -1, 2 };
 
    // Function call
    vector<int> ans
        = processQ(types.size(), types,
                   queries1, queries2);
    for (auto& x : ans)
        cout << x << " ";
    return 0;
}


Java




import java.util.*;
import java.io.*;
 
// Java program for the above approach
 
class GFG{
 
    // Function to find the final state of array
    static ArrayList<Integer> processQ(int Q,
                                       ArrayList<Integer> types,
                                       ArrayList<Integer> queries1,
                                       ArrayList<Integer> queries2)
    {
        // Initializing an unordered map
        HashMap<Integer, ArrayList<Integer>> indices =
          new HashMap<Integer, ArrayList<Integer>>();
 
        int cnt = 0;
        for (int i = 0 ; i < Q ; i++) {
            if (types.get(i) == 1) {
                if(!indices.containsKey(queries1.get(i))){
                    indices.put(queries1.get(i), new ArrayList<Integer>());
                }
                indices.get(queries1.get(i)).add(cnt++);
            }
            else {
                if(indices.containsKey(queries1.get(i))){
                    for (int x : indices.get(queries1.get(i))){
                        if(!indices.containsKey(queries2.get(i))){
                            indices.put(queries2.get(i), new ArrayList<Integer>());
                        }
                        indices.get(queries2.get(i)).add(x);
                    }
                    indices.get(queries1.get(i)).clear();
                }
            }
        }
 
        ArrayList<Integer> A = new ArrayList<Integer>();
        for(int i = 0 ; i < cnt ; i++){
            A.add(0);
        }
 
        for (Map.Entry<Integer, ArrayList<Integer>> x : indices.entrySet()){
            for (int y : x.getValue()){
                A.set(y, x.getKey());
            }
        }
 
        return A;
    }
 
    // Driver Code
    public static void main(String args[])
    {
        ArrayList<Integer> types = new ArrayList<Integer>(
            List.of( 1, 1, 2 )
        );
        ArrayList<Integer> queries1 = new ArrayList<Integer>(
            List.of( 1, 2, 1 )
        );
        ArrayList<Integer> queries2 = new ArrayList<Integer>(
            List.of( -1, -1, 2 )
        );
 
        // Function call
        ArrayList<Integer> ans = processQ(types.size(), types, queries1, queries2);
        for (int x : ans){
            System.out.print(x + " ");
        }
        System.out.println("");
       }
}
 
// This code is contributed by entertain2022.


Python3




# python3 code to implement the above approach
 
# Function to find the final state of array
def processQ(Q, types, queries1, queries2):
 
        # Initializing an unordered map
    indices = {}
    cnt = 0
    for i in range(0, Q):
        if (types[i] == 1):
            if queries1[i] in indices:
                indices[queries1[i]].append(cnt)
            else:
                indices[queries1[i]] = [cnt]
            cnt += 1
 
        else:
            if queries1[i] in indices:
                for x in indices[queries1[i]]:
                    if queries2[i] in indices:
                        indices[queries2[i]].append(x)
                    else:
                        indices[queries2[i]] = [x]
 
                indices[queries1[i]] = []
 
    A = [0 for _ in range(cnt)]
 
    for x in indices:
        for y in indices[x]:
            A[y] = x
 
    return A
 
# Driver code
if __name__ == "__main__":
 
    types = [1, 1, 2]
    queries1 = [1, 2, 1]
    queries2 = [-1, -1, 2]
 
    # Function call
    ans = processQ(len(types), types,
                   queries1, queries2)
    for x in ans:
        print(x, end=" ")
 
    # This code is contributed by rakeshsahni


C#




// C# program to implement above approach
using System;
using System.Collections;
using System.Collections.Generic;
 
class GFG
{
 
  // Function to find the final state of array
  static List<int> processQ(int Q, List<int> types, List<int> queries1, List<int> queries2)
  {
    // Initializing an unordered map
    Dictionary<int, List<int>> indices = new Dictionary<int, List<int>>();
    int cnt = 0;
    for (int i = 0 ; i < Q ; i++) {
      if (types[i] == 1) {
        if(!indices.ContainsKey(queries1[i])){
          indices.Add(queries1[i], new List<int>());
        }
        indices[queries1[i]].Add(cnt++);
      }
      else {
        if(indices.ContainsKey(queries1[i])){
          foreach (int x in indices[queries1[i]]){
            if(!indices.ContainsKey(queries2[i])){
              indices.Add(queries2[i], new List<int>());
            }
            indices[queries2[i]].Add(x);
          }
          indices[queries1[i]].Clear();
        }
      }
    }
 
    List<int> A = new List<int>();
    for(int i = 0 ; i < cnt ; i++){
      A.Add(0);
    }
 
    foreach (KeyValuePair<int, List<int>> x in indices) {
      foreach (int y in x.Value){
        A[y] = x.Key;
      }
    }
 
    return A;
  }
 
  // Driver code
  public static void Main(string[] args){
 
    List<int> types = new List<int>{ 1, 1, 2 };
    List<int> queries1 = new List<int>{ 1, 2, 1 };
    List<int> queries2 = new List<int>{ -1, -1, 2 };
 
    // Function call
    List<int> ans = processQ(types.Count, types, queries1, queries2);
    foreach (int x in ans){
      Console.Write(x + " ");
 
    }
  }
}
 
// This code is contributed by subhamgoyal2014.


Javascript




<script>
// JavaScript code to implement the above approach
 
// Function to find the final state of array
function processQ(Q, types, queries1, queries2)
{
 
    // Initializing an unordered object
    var indices = {};
    var cnt = 0;
    for (var i = 0; i < Q; i++)
    {
        if (types[i] == 1)
        {
            if (indices.hasOwnProperty(queries1[i]))
                indices[queries1[i]].push(cnt);
            else
                indices[queries1[i]] = [cnt];
            cnt += 1;
        }
 
        else
        {
            if (indices.hasOwnProperty(queries1[i]))
            {
                for (var j = 0; j < indices[queries1[i]].length; j++)
                {
                    var x = indices[queries1[i]][j];
                    if (indices.hasOwnProperty(queries2[i]))
                        indices[queries2[i]].push(x);
                    else
                        indices[queries2[i]] = [x];
                }
 
                indices[queries1[i]] = [];
            }
        }
    }
     
    var A = new Array(cnt).fill(0);
 
     
    for (const [keys, values] of Object.entries(indices))
    {
        for (var i = 0; i < values.length; i++)
        {
            var y = values[i];
            A[y] = keys;
        }
    }
         
    return A;
}
 
// Driver code
var types = [1, 1, 2];
var queries1 = [1, 2, 1];
var queries2 = [-1, -1, 2];
 
// Function call
var ans = processQ(types.length, types,
                   queries1, queries2);
for (var i = 0; i < ans.length; i++)
{
   document.write(ans[i] + " ");
}
 
// This code is contributed by phasing17
</script>


Output

2 2 

Time Complexity: O(Q * K) where K is the maximum size of the vector formed
Auxiliary Space: O(K)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads