Pre-requisites: Segment Tree

Given an array of digits arr[]. Given a number of range [L, R] and a digit X with each range. The task is to check for each given range [L, R] whether the digit X is present within that range in the array arr[].

Examples:

Input : arr = [1, 3, 3, 9, 8, 7] l1=0, r1=3, x=2 // Range 1 l1=2, r1=5, x=3 // Range 2 Output : NO YES For Range 1: The digit 2 is not present within range [0, 3] in the array. For Range 2: The digit 3 is present within the range [2, 5] at index 2 in the given array.

Naive Approach: A naive approach is to traverse through each of the given range of the digits in the array and check whether the digit is present or not.

Time Complexity: O(N) for each query.

Better Approach: A better approach is to use Segment Tree. Since there are only 10 digits possible from (0-9), so each node of the segment tree will contain all the digits within the range of that node. We will use Set Data Structure at every node to store the digits. Set is a special data structure which removes redundant elements and store them in ascending order. We have used set data structure since it will be easier to merge 2 child nodes to get the parent node in the segment tree. We will insert all the digits present in the children nodes in the parent set and it will automatically remove the redundant digits. Hence at every set(node) there will be at max 10 elements (0-9 all the digits).

Also there are inbuilt count function which returns the count of the element present in the set which will be helpful in the query function to check whether a digit is present at the node or not. If the count will be greater than 0 that means the element is present in the set we will return true else return false.

Below is the implementation of the above approach:



C++ filter_none edit

close play_arrow link

brightness_4

code #include <bits/stdc++.h> using namespace std; #define N 6 set< int > Tree[6 * N]; void buildTree( int * arr, int idx, int s, int e) { if (s == e) { Tree[idx].insert(arr[s]); return ; } int mid = (s + e) >> 1; buildTree(arr, 2 * idx, s, mid); buildTree(arr, 2 * idx + 1, mid + 1, e); for ( auto it : Tree[2 * idx]) { Tree[idx].insert(it); } for ( auto it : Tree[2 * idx + 1]) { Tree[idx].insert(it); } } bool query( int idx, int s, int e, int qs, int qe, int x) { if (qs <= s && e <= qe) { if (Tree[idx].count(x) != 0) { return true ; } else return false ; } if (qe < s || e < qs) { return false ; } int mid = (s + e) >> 1; bool LeftAns = query(2 * idx, s, mid, qs, qe, x); bool RightAns = query(2 * idx + 1, mid + 1, e, qs, qe, x); return LeftAns or RightAns; } int main() { int arr[] = { 1, 3, 3, 9, 8, 7 }; int n = sizeof (arr) / sizeof (arr[0]); buildTree(arr, 1, 0, n - 1); int l, r, x; l = 0, r = 3, x = 2; if (query(1, 0, n - 1, l, r, x)) cout << "YES" << '

' ; else cout << "NO" << '

' ; l = 2, r = 5, x = 3; if (query(1, 0, n - 1, l, r, x)) cout << "YES" << '

' ; else cout << "NO" << '

' ; return 0; } chevron_right filter_none Java filter_none edit

close play_arrow link

brightness_4

code import java.io.*; import java.util.*; class GFG { static int N = 6 ; @SuppressWarnings ( "unchecked" ) static HashSet<Integer>[] Tree = new HashSet[ 6 * N]; static { for ( int i = 0 ; i < 6 * N; i++) Tree[i] = new HashSet<>(); } static void buildTree( int [] arr, int idx, int s, int e) { if (s == e) { Tree[idx].add(arr[s]); return ; } int mid = (s + e) / 2 ; buildTree(arr, 2 * idx, s, mid); buildTree(arr, 2 * idx + 1 , mid + 1 , e); for ( int it : Tree[ 2 * idx]) Tree[idx].add(it); for ( int it : Tree[ 2 * idx + 1 ]) Tree[idx].add(it); } static boolean query( int idx, int s, int e, int qs, int qe, int x) { if (qs <= s && e <= qe) { if (Collections.frequency(Tree[idx], x) != 0 ) return true ; else return false ; } if (qe < s || e < qs) return false ; int mid = (s + e) / 2 ; boolean LeftAns = query( 2 * idx, s, mid, qs, qe, x); boolean RightAns = query( 2 * idx + 1 , mid + 1 , e, qs, qe, x); return (LeftAns || RightAns); } public static void main(String[] args) { int [] arr = { 1 , 3 , 3 , 9 , 8 , 7 }; int n = arr.length; buildTree(arr, 1 , 0 , n - 1 ); int l, r, x; l = 0 ; r = 3 ; x = 2 ; if (query( 1 , 0 , n - 1 , l, r, x)) System.out.println( "Yes" ); else System.out.println( "No" ); l = 2 ; r = 5 ; x = 3 ; if (query( 1 , 0 , n - 1 , l, r, x)) System.out.println( "Yes" ); else System.out.println( "No" ); } } chevron_right filter_none Python3 filter_none edit

close play_arrow link

brightness_4

code N = 6 Tree = [ 0 ] * ( 6 * N) for i in range ( 6 * N): Tree[i] = set () def buildTree(arr: list , idx: int , s: int , e: int ) - > None : global Tree if s = = e: Tree[idx].add(arr[s]) return mid = (s + e) / / 2 buildTree(arr, 2 * idx, s, mid) buildTree(arr, 2 * idx + 1 , mid + 1 , e) for it in Tree[ 2 * idx]: Tree[idx].add(it) for it in Tree[ 2 * idx + 1 ]: Tree[idx].add(it) def query(idx: int , s: int , e: int , qs: int , qe: int , x: int ) - > bool : global Tree if qs < = s and e < = qe: if list (Tree[idx]).count(x) ! = 0 : return True else : return False if qe < s or e < qs: return False mid = (s + e) / / 2 leftAns = query( 2 * idx, s, mid, qs, qe, x) rightAns = query( 2 * idx + 1 , mid + 1 , e, qs, qe, x) return (leftAns or rightAns) if __name__ = = "__main__" : arr = [ 1 , 3 , 3 , 9 , 8 , 7 ] n = len (arr) buildTree(arr, 1 , 0 , n - 1 ) l = 0 r = 3 x = 2 if query( 1 , 0 , n - 1 , l, r, x): print ( "YES" ) else : print ( "NO" ) l = 2 r = 5 x = 3 if query( 1 , 0 , n - 1 , l, r, x): print ( "YES" ) else : print ( "NO" ) chevron_right filter_none C# filter_none edit

close play_arrow link

brightness_4

code using System; using System.Collections.Generic; class GFG { static int N = 6; static SortedSet< int >[] Tree = new SortedSet< int >[6 * N]; static void buildTree( int [] arr, int idx, int s, int e) { if (s == e) { Tree[idx].Add(arr[s]); return ; } int mid = (s + e) / 2; buildTree(arr, 2 * idx, s, mid); buildTree(arr, 2 * idx + 1, mid + 1, e); foreach ( int it in Tree[2 * idx]) Tree[idx].Add(it); foreach ( int it in Tree[2 * idx + 1]) Tree[idx].Add(it); } static bool query( int idx, int s, int e, int qs, int qe, int x) { if (qs <= s && e <= qe) { if (Tree[idx].Contains(x)) return true ; else return false ; } if (qe < s || e < qs) return false ; int mid = (s + e) / 2; bool LeftAns = query(2 * idx, s, mid, qs, qe, x); bool RightAns = query(2 * idx + 1, mid + 1, e, qs, qe, x); return (LeftAns || RightAns); } public static void Main(String[] args) { int [] arr = { 1, 3, 3, 9, 8, 7 }; int n = arr.Length; for ( int i = 0; i < 6 * N; i++) Tree[i] = new SortedSet< int >(); buildTree(arr, 1, 0, n - 1); int l, r, x; l = 0; r = 3; x = 2; if (query(1, 0, n - 1, l, r, x)) Console.WriteLine( "Yes" ); else Console.WriteLine( "No" ); l = 2; r = 5; x = 3; if (query(1, 0, n - 1, l, r, x)) Console.WriteLine( "Yes" ); else Console.WriteLine( "No" ); } } chevron_right filter_none

Output: NO YES

Time Complexity: O(N) once for building the segment tree, then O(logN) for each query.

My Personal Notes arrow_drop_up Save