Replace all occurrences of X by Y or add element K in Array for Q queries
Last Updated :
01 Jul, 2022
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
#include <bits/stdc++.h>
using namespace std;
vector< int > processQ( int Q, vector< int > types,
vector< int > queries1,
vector< int > queries2)
{
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;
}
int main()
{
vector< int > types = { 1, 1, 2 };
vector< int > queries1 = { 1, 2, 1 };
vector< int > queries2 = { -1, -1, 2 };
vector< int > ans
= processQ(types.size(), types,
queries1, queries2);
for ( auto & x : ans)
cout << x << " " ;
return 0;
}
|
Java
import java.util.*;
import java.io.*;
class GFG{
static ArrayList<Integer> processQ( int Q,
ArrayList<Integer> types,
ArrayList<Integer> queries1,
ArrayList<Integer> queries2)
{
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;
}
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 )
);
ArrayList<Integer> ans = processQ(types.size(), types, queries1, queries2);
for ( int x : ans){
System.out.print(x + " " );
}
System.out.println( "" );
}
}
|
Python3
def processQ(Q, types, queries1, queries2):
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
if __name__ = = "__main__" :
types = [ 1 , 1 , 2 ]
queries1 = [ 1 , 2 , 1 ]
queries2 = [ - 1 , - 1 , 2 ]
ans = processQ( len (types), types,
queries1, queries2)
for x in ans:
print (x, end = " " )
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG
{
static List< int > processQ( int Q, List< int > types, List< int > queries1, List< int > queries2)
{
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;
}
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 };
List< int > ans = processQ(types.Count, types, queries1, queries2);
foreach ( int x in ans){
Console.Write(x + " " );
}
}
}
|
Javascript
<script>
function processQ(Q, types, queries1, queries2)
{
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;
}
var types = [1, 1, 2];
var queries1 = [1, 2, 1];
var queries2 = [-1, -1, 2];
var ans = processQ(types.length, types,
queries1, queries2);
for ( var i = 0; i < ans.length; i++)
{
document.write(ans[i] + " " );
}
</script>
|
Time Complexity: O(Q * K) where K is the maximum size of the vector formed
Auxiliary Space: O(K)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...