先决条件:段树
给定一个数字数组arr [] 。给定多个范围[L,R]和每个范围的数字X。任务是检查每个给定范围[L,R]数组arr []中的数字X是否在该范围内。
例子:
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.
天真的方法:天真的方法是遍历数组中每个给定数字范围,并检查该数字是否存在。
时间复杂度:每个查询为O(N)。
更好的方法:更好的方法是使用段树。由于(0-9)只能有10位数字,因此段树的每个节点都将包含该节点范围内的所有数字。我们将在每个节点上使用“设置数据结构”来存储数字。 Set是一种特殊的数据结构,它删除冗余元素并按升序存储它们。我们使用集合数据结构是因为合并两个子节点以在段树中获得父节点会更容易。我们将在父集中的子节点中插入所有存在的数字,它将自动删除多余的数字。因此,在每个集合(节点)处最多将有10个元素(所有数字为0-9)。
还有内置的计数函数,它返回集合中存在的元素的计数,这将有助于查询函数检查节点上是否存在数字。如果计数大于0,则表示该元素存在于集合中,我们将返回true,否则返回false。
下面是上述方法的实现:
C++
// CPP program to answer Queries to check whether
// a given digit is present in the given range
#include
using namespace std;
#define N 6
// Segment Tree with set at each node
set Tree[6 * N];
// Funtiom to build the segment tree
void buildTree(int* arr, int idx, int s, int e)
{
if (s == e) {
Tree[idx].insert(arr[s]);
return;
}
int mid = (s + e) >> 1;
// Left child node
buildTree(arr, 2 * idx, s, mid);
// Right child node
buildTree(arr, 2 * idx + 1, mid + 1, e);
// Merging child nodes to get parent node.
// Since set is used, it will remove
// redundant digits.
for (auto it : Tree[2 * idx]) {
Tree[idx].insert(it);
}
for (auto it : Tree[2 * idx + 1]) {
Tree[idx].insert(it);
}
}
// Function to query a range
bool query(int idx, int s, int e, int qs, int qe, int x)
{
// Complete Overlapp condition
// return true if digit is present.
// else false.
if (qs <= s && e <= qe) {
if (Tree[idx].count(x) != 0) {
return true;
}
else
return false;
}
// No Overlapp condition
// Return false
if (qe < s || e < qs) {
return false;
}
int mid = (s + e) >> 1;
// If digit is found in any child
// return true, else False
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;
}
// Driver Code
int main()
{
int arr[] = { 1, 3, 3, 9, 8, 7 };
int n = sizeof(arr) / sizeof(arr[0]);
// Build the tree
buildTree(arr, 1, 0, n - 1);
int l, r, x;
// Query 1
l = 0, r = 3, x = 2;
if (query(1, 0, n - 1, l, r, x))
cout << "YES" << '\n';
else
cout << "NO" << '\n';
// Query 2
l = 2, r = 5, x = 3;
if (query(1, 0, n - 1, l, r, x))
cout << "YES" << '\n';
else
cout << "NO" << '\n';
return 0;
}
Java
// Java program to answer Queries to check whether
// a given digit is present in the given range
import java.io.*;
import java.util.*;
class GFG
{
static int N = 6;
// Segment Tree with set at each node
@SuppressWarnings("unchecked")
static HashSet[] Tree = new HashSet[6 * N];
static
{
for (int i = 0; i < 6 * N; i++)
Tree[i] = new HashSet<>();
}
// Funtiom to build the segment tree
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;
// Left child node
buildTree(arr, 2 * idx, s, mid);
// Right child node
buildTree(arr, 2 * idx + 1, mid + 1, e);
// Merging child nodes to get parent node.
// Since set is used, it will remove
// redundant digits.
for (int it : Tree[2 * idx])
Tree[idx].add(it);
for (int it : Tree[2 * idx + 1])
Tree[idx].add(it);
}
// Function to query a range
static boolean query(int idx, int s, int e,
int qs, int qe, int x)
{
// Complete Overlapp condition
// return true if digit is present.
// else false.
if (qs <= s && e <= qe)
{
if (Collections.frequency(Tree[idx], x) != 0)
return true;
else
return false;
}
// No Overlapp condition
// Return false
if (qe < s || e < qs)
return false;
int mid = (s + e) / 2;
// If digit is found in any child
// return true, else False
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);
}
// Driver Code
public static void main(String[] args)
{
int[] arr = { 1, 3, 3, 9, 8, 7 };
int n = arr.length;
// Build the tree
buildTree(arr, 1, 0, n - 1);
int l, r, x;
// Query 1
l = 0;
r = 3;
x = 2;
if (query(1, 0, n - 1, l, r, x))
System.out.println("Yes");
else
System.out.println("No");
// Query 2
l = 2;
r = 5;
x = 3;
if (query(1, 0, n - 1, l, r, x))
System.out.println("Yes");
else
System.out.println("No");
}
}
// This code is contributed by
// sanjeev2552
Python3
# Python3 program to answer Queries to check whether
# a given digit is present in the given range
N = 6
# Segment Tree with set at each node
Tree = [0] * (6 * N)
for i in range(6 * N):
Tree[i] = set()
# Funtiom to build the segment tree
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
# Left child node
buildTree(arr, 2 * idx, s, mid)
# Right child node
buildTree(arr, 2 * idx + 1, mid + 1, e)
# Merging child nodes to get parent node.
# Since set is used, it will remove
# redundant digits.
for it in Tree[2 * idx]:
Tree[idx].add(it)
for it in Tree[2 * idx + 1]:
Tree[idx].add(it)
# Function to query a range
def query(idx: int, s: int, e: int,
qs: int, qe: int, x: int) -> bool:
global Tree
# Complete Overlapp condition
# return true if digit is present.
# else false.
if qs <= s and e <= qe:
if list(Tree[idx]).count(x) != 0:
return True
else:
return False
# No Overlapp condition
# Return false
if qe < s or e < qs:
return False
mid = (s + e) // 2
# If digit is found in any child
# return true, else False
leftAns = query(2 * idx, s, mid, qs, qe, x)
rightAns = query(2 * idx + 1,
mid + 1, e, qs, qe, x)
return (leftAns or rightAns)
# Driver Code
if __name__ == "__main__":
arr = [1, 3, 3, 9, 8, 7]
n = len(arr)
# Build the tree
buildTree(arr, 1, 0, n - 1)
# Query 1
l = 0
r = 3
x = 2
if query(1, 0, n - 1, l, r, x):
print("YES")
else:
print("NO")
# Query 2
l = 2
r = 5
x = 3
if query(1, 0, n - 1, l, r, x):
print("YES")
else:
print("NO")
# This code is contributed by
# sanjeev2552
C#
// C# program to answer Queries to check whether
// a given digit is present in the given range
using System;
using System.Collections.Generic;
class GFG
{
static int N = 6;
// Segment Tree with set at each node
static SortedSet[] Tree = new SortedSet[6 * N];
// Funtiom to build the segment tree
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;
// Left child node
buildTree(arr, 2 * idx, s, mid);
// Right child node
buildTree(arr, 2 * idx + 1, mid + 1, e);
// Merging child nodes to get parent node.
// Since set is used, it will remove
// redundant digits.
foreach (int it in Tree[2 * idx])
Tree[idx].Add(it);
foreach (int it in Tree[2 * idx + 1])
Tree[idx].Add(it);
}
// Function to query a range
static bool query(int idx, int s, int e,
int qs, int qe, int x)
{
// Complete Overlapp condition
// return true if digit is present.
// else false.
if (qs <= s && e <= qe)
{
if (Tree[idx].Contains(x))
return true;
else
return false;
}
// No Overlapp condition
// Return false
if (qe < s || e < qs)
return false;
int mid = (s + e) / 2;
// If digit is found in any child
// return true, else False
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);
}
// Driver Code
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();
// Build the tree
buildTree(arr, 1, 0, n - 1);
int l, r, x;
// Query 1
l = 0;
r = 3;
x = 2;
if (query(1, 0, n - 1, l, r, x))
Console.WriteLine("Yes");
else
Console.WriteLine("No");
// Query 2
l = 2;
r = 5;
x = 3;
if (query(1, 0, n - 1, l, r, x))
Console.WriteLine("Yes");
else
Console.WriteLine("No");
}
}
// This code is contributed by Rajput-Ji
输出:
NO
YES
时间复杂度:一次O(N)用于构建细分树,然后对每个查询进行O(logN)。
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。