What data structure to find number of elements in a given range in O(log n) time?

Though not part of STL, you may use Policy-Based Data Structures which are part of gcc extensions; In particular you may initialize an order statistics tree as below. The code compiles with gcc without any external libraries:

#include<iostream>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

int main()
{
    tree<int,         /* key                */
         null_type,   /* mapped             */
         less<int>,   /* compare function   */
         rb_tree_tag, /* red-black tree tag */
         tree_order_statistics_node_update> tr;

    for(int i = 0; i < 20; ++i)
        tr.insert(i);

    /* number of elements in the range [3, 10) */
    cout << tr.order_of_key(10) - tr.order_of_key(3);
}

Although the standard library is indeed well-featured, I don't think you'll find anything with these particular requirements in there. As you noted, the set-like structures return non-random-access iterators -- to provide random access (or some kind of distance function, as you require) would introduce significant complexity.

You may be able to achieve your goal by implementing an indexable skip list, which provides O(log(n)) insertion, deletion, and indexed lookup, as described here: https://en.wikipedia.org/wiki/Skip_list#Indexable_skiplist

A guide to implementation can be found here: http://cg.scs.carleton.ca/~morin/teaching/5408/refs/p90b.pdf


The two obvious data structures for this task are the skip list (which Jack O'Reilly has already mentioned) and some variant of the order statistic tree (which Behzad mentions but doesn't really explain).

An order statistic tree stores one extra piece of information in each node. You can store any of a number of different things, but the one I find easiest to understand is if each node stores the number of elements in its left sub-tree.

When you insert, as you walk down the tree to store an element, you increment the count every time you descend to the left in the tree. Since you're only modifying the nodes you'd traverse anyway, this doesn't change the O(log N) insertion. When you re-balance, you have to adjust accordingly (but, again, you're only modifying counts in nodes you're already modifying when you do rotations, so (again) you don't affect the overall complexity.

When you need to find a distance from one element to another, you just find the two nodes, each with O(log N) complexity. You get the index of each element in the tree as you find it by initializing an index from the root, then updating it from there (subtract the count as you descend to the left, add as you descend to the right).


You should be able to accomplish this with a standard or slightly modified B-Tree.

Typically most standard operations are O(log(n)) for B-Tree implementations.


It certainly isn't the most space efficient, giving O(3n), but it satisfies the insert, remove and distance criteria listed above. The following uses a linked list, map and unordered_map.

The list is used to maintain order. Normally inserting into a list in order is linear time, but with help from a map of key to list_iterator, we can insert in constant time. The advantage of storing ordered data in a list is that it uses random access iterators meaning you can get a constant time std::distance call

The map is used to get a hint as to where in the list to insert a node. This is done by creating a new map entry for the given key, then decrementing the iterator by 1. The value of this new iterator gives us the appropriate insert position into the linked list.

The unordered_map gives us o(1) lookup for random access list iterators, allowing us to get a o(logn) remove and distance time.

class logn
{
public:
    using list_it = std::list<int>::iterator;

    void insert(int i)
    {
        const bool first = list.empty();
        auto original_it = map.insert({i,list.end()}).first; // o(logn)
        auto hint = original_it;
        if (!first)
            --hint; 
        umap[i] = list.insert(hint->second,i);  // o(1)
        original_it->second = umap[i]; 
    }

    void remove(int i)
    {
        auto it = umap.find(i); // o(1)
        list.erase(it->second); // o(1)
        umap.erase(it);         // o(1)
        map.erase(map.find(i)); // o(logn)
    }

    list_it get(int i) const
    {
        return umap.find(i)->second;
    }

    unsigned int distance(int lower, int upper) const
    {
        return std::distance(get(lower), get(upper));
    }

private:

    std::list<int> list;
    std::unordered_map<int, list_it> umap;
    std::map<int, list_it> map;

};

Comments

  1. Young

    • 2016/12/7

    Given with array, L, R, P as an input and the task is to find the ranges between L and R Questions and Answers · Effective Resume Writing · HR Interview As given in the figure we have array of elements and L which is a Left value as 2 Now the program must find the products of ranges between them.

  2. Gunnar

    • 2019/10/29

    Maximum difference between two elements in an Array; Maximum difference between two elements such that larger element appears after the smaller number; Finding sum of digits of a number until sum becomes single digit; Program for Sum of the digits of a given number; Compute sum of digits in all numbers from 1 to n; Count possible ways to

  3. Preston

    • 2020/4/9

    Calculate the length of the array that is a number of elements present in the array. in an array can be found using len(); print("Number of elements present in given array: " + str(len(arr))); Arrays in Java are created using a new keyword as.

  4. Lukas

    • 2018/3/28

    Given two arrays of numbers find the common unique elements. I'd say these arrays are sounding a hell of a lot like a set data structure, and this set data structure, because we want to find the intersection between these two sets. In java this would be:

  5. Nelson

    • 2016/5/11

    Approach used in the below program is as follows. Input an array let's say, int arr[] Calculate the length of both the arrays using the length() function that will return an integer value as per the elements in an array. Start the loop from i to 0 till i less than size of an array.

  6. Moshe

    • 2020/12/22

    Given an unsorted array of size n, find no of elements between two elements i and j (both inclusive). Examples: Input : arr = [1 3 3 9 10 4] i1 = 1, j1 = 4 i2 = 9, j2 = 12 Output : 4 2 The numbers are: 1 3 3 4 for first query The numbers are: 9 10 for second query

  7. Watson

    • 2020/5/20

    Given an unsorted array of n elements and also given two points num1 and num2​. The task is to count number of elements occurs between the 

  8. Roger

    • 2018/12/30

    Find all elements count in list in Python; Count occurrence of all elements of list in a tuple in Python; Count distinct elements in an array in Python; Python - Check if frequencies of all characters of a string are different; Check if all array elements are distinct in Python; Count number of elements between two given elements in array in C++

  9. Maverick

    • 2019/1/21

    Given an unsorted array of n elements and also given two points num1 and num2​. The task is to count number of elements occurs between the 

  10. Marc

    • 2015/12/25

    Given an array of n non-negative integers. The task is to find frequency of a particular element in the arbitrary range of array []. The range is given as positions (not 0 based indexes) in array. There can be multiple queries of given type.

  11. Heath

    • 2018/8/9

    . Each additional layer of links contains fewer elements, but no new elements.

  12. Dennis

    • 2021/4/18

    A skip list is built in layers. The bottom layer is an ordinary ordered linked list.Each higher layer acts as an "express lane" for the lists below, where an element in layer appears in layer + with some fixed probability (two commonly used values for are / or /).

  13. Kylen

    • 2021/1/6

    Apr 21, 2020

  14. Yousef

    • 2019/9/2

    Previous: Write a C program to find the largest value from first, last, and middle elements of a given array of integers of odd length (atleast 1). Next: Write a C program to compute the sum of values in a given array of integers except the number 17. Return 0 if the given array has no integer. 

  15. Roux

    • 2018/5/14

    Found a second bug in addition to the one mentioned by Alex D: class PTemp{ int first = -1; int second = -1; public PTemp(int first, int second){ 

  16. Forrest

    • 2020/2/3

    An Efficient Approach will be to first sort the array and then using a modified binary search function find two indices, one of first element greater than or equal to lower bound of range and the other of the last element less than or equal to upperbound. Time for running each query will be O(logn) and for sorting the array once will be O(nlogn).

  17. Castillo

    • 2018/4/30

    Given an Array of bad numbers and a range of integers, how can I determine the longest segment of integers within that inclusive range that doesn't contain a bad number? Segments without bad numbers are [3,6],[8,14],[16,21],[23,36] and [38,48]. The longest segment is [23,36] and it is 14 elements long.

  18. Leone

    • 2017/1/20

    For example, you are given the lower limit l=3 and the upper limit r = 48, The array badNumbers = [37,7,22,15,49,60]. Segments without bad numbers are [3,6], [8,14], [16,21], [23,36] and [38,48]. The longest segment is [23,36] and it is 14 elements long. Problem : Function Description Complete the function goodStatement in the editor below.

  19. Dylan

    • 2020/3/28

    Found a second bug in addition to the one mentioned by Alex D: class PTemp{ int first = -1; int second = -1; public PTemp(int first, int second){ 

  20. Kellan

    • 2018/9/13

    Given an unsorted array of size n, find no of elements between two elements i and j (both inclusive). Examples: Input : arr = [1 3 3 9 10 4] i1 = 1, j1 = 4 i2 = 9, j2 = 12 Output : 4 2 The numbers are: 1 3 3 4 for first query The numbers are: 9 10 for second query

  21. Javier

    • 2017/1/14

    The simplest approach to solve this problem is as follows: For the query of type (1 L R), iterate over the entire array and count the number of elements in the array such that L ≤ arr[i] ≤ R. Finally, print the count. For the query of type (2 i x), replace arr[i] by x.

  22. Bentlee

    • 2018/12/19

    The count of array elements with value in given range is 2 Updating Value The count of array elements with value in given range is 7 The solution to approach iterate once for every loop. Hence its time complexity is of the order O (Q*N). A better approach to solving the problem could be using the Binary Indexed Tree or Fenwick Tree data structure.

  23. Jacoby

    • 2018/3/3

    Get code examples like "check if array contains all elements of another array" instantly right from your google search results with the Grepper Chrome Extension.

  24. Vincent

    • 2015/8/24

    Checking array elements using the for loop Sometimes, you need to test whether every element of an array satisfies a specified condition. Typically, you use a for loop to iterate all elements and check each individual element against the condition. Suppose that you have an array numbers with three elements:

  25. Saint

    • 2017/8/30

    not.

  26. Joel

    • 2019/8/30

    Write a program to find the range of the elements in the array. Range of an array is the difference between the maximum and minimum element in an array, Input and Output Format: Input consists of n+1 integers where n corresponds to the number of elements in the array.

  27. Cruz

    • 2015/7/7

    Python List Exercises, Practice and Solution: Write a Python program to count the number of elements in a list within a specified range.

  28. Mitchell

    • 2018/12/18

    Python: check if two lists are equal or not ( covers both Ordered & Unordered lists) Compare & get differences between two lists in Python; Python : Count elements in a list that satisfy certain conditions; Python : 3 ways to check if there are duplicates in a List; Convert 2D NumPy array to list of lists in python

  29. Hezekiah

    • 2019/1/15

    A simple approach will be to run a for loop to check if each element is in the given range and maintain their count. Time complexity for running each query will be O​ 

  30. Uriah

    • 2018/10/18

    Query 4 is of type 2 : As stated in the definition of this type of query we will execute the queries stated in the range i.e. we will operate the queries instead of the array. The range given is 1 and 3 so we will execute queries 1, 2 and 3 again i.e. using repetitive approach queries 1, 2 and 3 will be executed.

  31. Jamir

    • 2015/6/2

    C program to count the frequency of each element in an array – In this article, we a.2) If any two element are equal to each other then increase the count value 

  32. Ashton

    • 2017/7/4

    Answer for Query 1 = 1 Answer for Query 2 = 0 Answer for Query 3 = 2 Answer for Query 4 = 1 Answer for Query 5 = 1 Answer for Query 6 = 3 Time Complexity of this approach using MO’s Algorithm is O(Q * sqrt(N) * logA) where logA is the complexity to insert an element A into the unordered_map for each query.

  33. Alonso

    • 2020/6/17

    Given an array of integers, find the length of the longest in the subsequence are consecutive integers, the consecutive numbers can be in any 

  34. Scott

    • 2016/2/23

    Given an array of bad numbers and a range of integers determine the longest segment of integers. Determine the longest segment of integers within an inclusive range , For example, you are given the lower limit l=3 and the upper limit r = 48, The array badNumbers = [37,7,22,15,49,60]. Segments without bad Given an Array of bad numbers and a

  35. Sam

    • 2019/1/23

    Approach used in the below program is as follows. Input an array let's say, int arr[] Calculate the length of both the arrays using the length() function that will return an integer value as per the elements in an array. Start the loop from i to 0 till i less than size of an array.

  36. Jase

    • 2015/6/28

    If you only want to count all elements: Assuming array can only contain a limited range of integers, declare another array of length the maximum entry in the first array. Iterate through the first array and increment the location in the second array index by the first array, then print out the second array.

  37. Marku

    • 2016/5/26

    Optional and by default 1 . Range returns a sequence of numbers that begins at start and ends before stop . The difference between the elements 

  38. Remy

    • 2016/4/1

    Calculate the length of the array that is a number of elements present in the array. Python. Arrays in Python is declared as. ArrayName = [ele1, ele2,]; be found using len(); print("Number of elements present in given array: " + str(len(arr​)));.

  39. Gianni

    • 2019/5/3

    Given an unsorted array of n elements and also given two points num1 and num2. The task is to count number of elements occurs between the given points (excluding num1 and num2). If there are multiple occurrences of num1 and num2, we need to consider leftmost occurrence of num1 and rightmost occurrence of num2.

Comments are closed.

Recent Posts