Queries to search an element in an array and move it to front after every query
Given an integer M which represents an array initially having numbers 1 to M. Also given is a Query array. For every query, search the number in the initial array and bring it to the front of the array. The task is to return the indexes of the searched element in the given array for every query.
Examples:
Input : Q[] = {3, 1, 2, 1}, M = 5
Output : [2, 1, 2, 1]
Explanations :
Since m = 5 the initial array is [1, 2, 3, 4, 5].
Query1: Search for 3 in the [1, 2, 3, 4, 5] and move it in the beginning. After moving, the array looks like [3, 1, 2, 4, 5]. 3 is at index 2.
Query2: Move 1 from [3, 1, 2, 4, 5] to the beginning of the array to make the array look like [1, 3, 2, 4, 5]. 1 is present at index 1.
Query3: Move 2 from [1, 3, 2, 4, 5] to the beginning of the array to make the array look like [2, 1, 3, 2, 4, 5]. 2 is present at index 2.
Query4: Move 1 from [2, 1, 3, 4, 5] to the beginning of the array to make the array look like [1, 2, 3, 4, 5]. 1 is present at index 1.
Input : Q[] = {4, 1, 2, 2}, M = 4
Output : 3, 1, 2, 0
Naive approach: The naive approach is to use a hash table to search for the element and linearly do shifts by performing swaps. The time complexity will be quadratic in nature for this approach.
Below is the naive implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > processQueries( int Q[], int m, int n)
{
int a[m + 1], pos[m + 1];
for ( int i = 1; i <= m; i++) {
a[i - 1] = i;
pos[i] = i - 1;
}
vector< int > ans;
for ( int i = 0; i < n; i++) {
int q = Q[i];
int p = pos[q];
ans.push_back(p);
for ( int i = p; i > 0; i--) {
swap(a[i], a[i - 1]);
pos[a[i]] = i;
}
pos[a[0]] = 0;
}
return ans;
}
int main()
{
int Q[] = { 3, 1, 2, 1 };
int n = sizeof (Q) / sizeof (Q[0]);
int m = 5;
vector< int > ans;
ans = processQueries(Q, m, n);
for ( int i = 0; i < ans.size(); i++)
cout << ans[i] << " " ;
return 0;
}
|
Java
import java.util.*;
class GFG{
static Vector<Integer> processQueries( int Q[], int m, int n)
{
int []a = new int [m + 1 ];
int []pos = new int [m + 1 ];
for ( int i = 1 ; i <= m; i++) {
a[i - 1 ] = i;
pos[i] = i - 1 ;
}
Vector<Integer> ans = new Vector<Integer>();
for ( int i = 0 ; i < n; i++) {
int q = Q[i];
int p = pos[q];
ans.add(p);
for ( int j = p; j > 0 ; j--) {
a[j] = a[j] + a[j - 1 ];
a[j - 1 ] = a[j] - a[j - 1 ];
a[j] = a[j] - a[j - 1 ];
pos[a[j]] = j;
}
pos[a[ 0 ]] = 0 ;
}
return ans;
}
public static void main(String[] args)
{
int Q[] = { 3 , 1 , 2 , 1 };
int n = Q.length;
int m = 5 ;
Vector<Integer> ans = new Vector<Integer>();
ans = processQueries(Q, m, n);
for ( int i = 0 ; i < ans.size(); i++)
System.out.print(ans.get(i)+ " " );
}
}
|
Python3
def processQueries(Q, m, n) :
a = [ 0 ] * (m + 1 ); pos = [ 0 ] * (m + 1 );
for i in range ( 1 , m + 1 ) :
a[i - 1 ] = i;
pos[i] = i - 1 ;
ans = [];
for i in range (n) :
q = Q[i];
p = pos[q];
ans.append(p);
for i in range (p, 0 , - 1 ) :
a[i], a[i - 1 ] = a[i - 1 ],a[i];
pos[a[i]] = i;
pos[a[ 0 ]] = 0 ;
return ans;
if __name__ = = "__main__" :
Q = [ 3 , 1 , 2 , 1 ];
n = len (Q);
m = 5 ;
ans = [];
ans = processQueries(Q, m, n);
for i in range ( len (ans)) :
print (ans[i],end = " " );
|
C#
using System;
using System.Collections.Generic;
public class GFG{
static List< int > processQueries( int []Q, int m, int n)
{
int []a = new int [m + 1];
int []pos = new int [m + 1];
for ( int i = 1; i <= m; i++)
{
a[i - 1] = i;
pos[i] = i - 1;
}
List< int > ans = new List< int >();
for ( int i = 0; i < n; i++)
{
int q = Q[i];
int p = pos[q];
ans.Add(p);
for ( int j = p; j > 0; j--)
{
a[j] = a[j] + a[j - 1];
a[j - 1] = a[j] - a[j - 1];
a[j] = a[j] - a[j - 1];
pos[a[j]] = j;
}
pos[a[0]] = 0;
}
return ans;
}
public static void Main(String[] args)
{
int []Q = { 3, 1, 2, 1 };
int n = Q.Length;
int m = 5;
List< int > ans = new List< int >();
ans = processQueries(Q, m, n);
for ( int i = 0; i < ans.Count; i++)
Console.Write(ans[i] + " " );
}
}
|
Javascript
<script>
function processQueries(Q,m,n)
{
let a = new Array(m + 1);
let pos = new Array(m + 1);
for (let i = 1; i <= m; i++) {
a[i - 1] = i;
pos[i] = i - 1;
}
let ans = [];
for (let i = 0; i < n; i++) {
let q = Q[i];
let p = pos[q];
ans.push(p);
for (let j = p; j > 0; j--) {
a[j] = a[j] + a[j - 1];
a[j - 1] = a[j] - a[j - 1];
a[j] = a[j] - a[j - 1];
pos[a[j]] = j;
}
pos[a[0]] = 0;
}
return ans;
}
let Q=[3, 1, 2, 1];
let n = Q.length;
let m = 5;
let ans=[];
ans = processQueries(Q, m, n);
for (let i = 0; i < ans.length; i++)
document.write(ans[i]+ " " );
</script>
|
Time complexity: O(n*p)
Auxiliary space: O(m)
Efficient Approach: An efficient method to solve the above problem is to use Fenwick Tree. Using the below 3 operations, the problem can be solved.
- Push element in the front
- Find the index of a number
- Update the indexes of the rest of the elements.
Keep the elements in a sorted manner using the set data structure, and then follow the below-mentioned points:
- Instead of pushing the element to the front i.e assigning an index 0 for every query.
- We assign -1 for the first query, -2 for the second query, -3 for the third, and so on till -m.
- Doing so, the range of index’s updates to [-m, m]
- Perform a right shift for all values [-m, m] by a value of m, so our new range is [0, 2m]
- Initialize a Fenwick tree of size 2m and set all the values from [1…m] i.e [m..2m]
- For every query, find its position by finding the number of set elements lesser than the given query, once done set its position to 0 in the Fenwick tree.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void update(vector< int >& tree, int i, int val)
{
while (i < tree.size()) {
tree[i] += val;
i += (i & (-i));
}
}
int getSum(vector< int >& tree, int i)
{
int s = 0;
while (i > 0) {
s += tree[i];
i -= (i & (-i));
}
return s;
}
vector< int > processQueries(vector< int >& queries, int m)
{
vector< int > res, tree((2 * m) + 1, 0);
unordered_map< int , int > hmap;
for ( int i = 1; i <= m; ++i) {
hmap[i] = i + m;
update(tree, i + m, 1);
}
for ( int querie : queries) {
res.push_back(getSum(tree, hmap[querie]) - 1);
update(tree, hmap[querie], -1);
update(tree, m, 1);
hmap[querie] = m;
m--;
}
return res;
}
int main()
{
vector< int > Queries = { 4, 1, 2, 2 };
int m = 4;
vector< int > ans;
ans = processQueries(Queries, m);
for ( int i = 0; i < ans.size(); i++)
cout << ans[i] << " " ;
return 0;
}
|
Java
import java.util.*;
class GFG{
static void update( int []tree, int i, int val)
{
while (i < tree.length)
{
tree[i] += val;
i += (i & (-i));
}
}
static int getSum( int []tree, int i)
{
int s = 0 ;
while (i > 0 )
{
s += tree[i];
i -= (i & (-i));
}
return s;
}
static Vector<Integer> processQueries( int []queries,
int m)
{
Vector<Integer>res = new Vector<>();
int []tree = new int [( 2 * m) + 1 ];
HashMap<Integer,Integer> hmap = new HashMap<>();
for ( int i = 1 ; i <= m; ++i)
{
hmap.put(i, i+m);
update(tree, i + m, 1 );
}
for ( int querie : queries)
{
res.add(getSum(tree, hmap.get(querie) - 1 ));
update(tree, hmap.get(querie), - 1 );
update(tree, m, 1 );
hmap.put(querie, m);
m--;
}
return res;
}
public static void main(String[] args)
{
int []Queries = { 4 , 1 , 2 , 2 };
int m = 4 ;
Vector<Integer> ans;
ans = processQueries(Queries, m);
System.out.print(ans);
}
}
|
Python3
def update(tree, i, val):
while (i < len (tree)):
tree[i] + = val
i + = (i & ( - i))
def getSum(tree, i):
s = 0
while (i > 0 ):
s + = tree[i]
i - = (i & ( - i))
return s
def processQueries(queries, m):
res = []
tree = [ 0 ] * ( 2 * m + 1 )
hmap = {}
for i in range ( 1 , m + 1 ):
hmap[i] = i + m
update(tree, i + m, 1 )
for querie in queries:
res.append(getSum(tree, hmap[querie]) - 1 )
update(tree, hmap[querie], - 1 )
update(tree, m, 1 )
hmap[querie] = m
m - = 1
return res
if __name__ = = "__main__" :
Queries = [ 4 , 1 , 2 , 2 ]
m = 4
ans = processQueries(Queries, m)
for i in range ( len (ans)):
print (ans[i], end = " " )
|
C#
using System;
using System.Collections.Generic;
class GFG{
static void update( int []tree,
int i, int val)
{
while (i < tree.Length)
{
tree[i] += val;
i += (i & (-i));
}
}
static int getSum( int []tree, int i)
{
int s = 0;
while (i > 0)
{
s += tree[i];
i -= (i & (-i));
}
return s;
}
static List< int > processQueries( int []queries,
int m)
{
List< int >res = new List< int >();
int []tree = new int [(2 * m) + 1];
Dictionary< int ,
int > hmap = new Dictionary< int ,
int >();
for ( int i = 1; i <= m; ++i)
{
hmap.Add(i, i+m);
update(tree, i + m, 1);
}
foreach ( int querie in queries)
{
res.Add(getSum(tree, hmap[querie] - 1));
update(tree, hmap[querie], -1);
update(tree, m, 1);
if (hmap.ContainsKey(querie))
hmap[querie] = m;
else
hmap.Add(querie, m);
m--;
}
return res;
}
public static void Main(String[] args)
{
int []Queries = {4, 1, 2, 2};
int m = 4;
List< int > ans;
ans = processQueries(Queries, m);
foreach ( int i in ans)
Console.Write(i + " " );
}
}
|
Javascript
<script>
function update(tree,i,val)
{
while (i < tree.length)
{
tree[i] += val;
i += (i & (-i));
}
}
function getSum(tree,i)
{
let s = 0;
while (i > 0)
{
s += tree[i];
i -= (i & (-i));
}
return s;
}
function processQueries(queries,m)
{
let res = [];
let tree = new Array((2 * m) + 1);
for (let i=0;i<tree.length;i++)
{
tree[i]=0;
}
let hmap = new Map();
for (let i = 1; i <= m; ++i)
{
hmap.set(i, i+m);
update(tree, i + m, 1);
}
for (let querie=0;querie< queries.length;querie++)
{
res.push(getSum(tree, hmap.get(queries[querie]) - 1));
update(tree, hmap.get(queries[querie]), -1);
update(tree, m, 1);
hmap.set(queries[querie], m);
m--;
}
return res;
}
let Queries=[4, 1, 2, 2];
let m = 4;
let ans;
ans = processQueries(Queries, m);
document.write(ans.join( " " ));
</script>
|
Time complexity: O(nlogn)
Auxiliary space: O(n)
Last Updated :
27 Sep, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...