Given an array of n numbers and a number k. You have to write a program to find the number of subarrays with xor less than k.
Examples:
Input: arr[] = {8, 9, 10, 11, 12}, k=3
Output: 4
Explanation: Sub-arrays [1:3], [2:3], [2:5], [4:5] have xor values 2, 1, 0, 1 respectively.
Input: arr[] = {12, 4, 6, 8, 21}, k=8
Output: 4
Naive Approach: The naive algorithm is to simply calculate the xor value of each and every subarray and compare it with the given number k to find the answer.
Below is the implementation of the above approach:
C++
#include <iostream>
using namespace std;
int xorLessK( int arr[], int n, int k)
{
int count = 0;
for ( int i = 0; i < n; i++) {
int tempXor = 0;
for ( int j = i; j < n; j++) {
tempXor ^= arr[j];
if (tempXor < k)
count++;
}
}
return count;
}
int main()
{
int n, k = 3;
int arr[] = { 8, 9, 10, 11, 12 };
n = sizeof (arr) / sizeof (arr[0]);
cout << xorLessK(arr, n, k);
return 0;
}
|
Java
import java.io.*;
class GFG {
static int xorLessK( int arr[], int n, int k)
{
int count = 0 ;
for ( int i = 0 ; i < n; i++) {
int tempXor = 0 ;
for ( int j = i; j < n; j++) {
tempXor ^= arr[j];
if (tempXor < k)
count++;
}
}
return count;
}
public static void main (String[] args) {
int k = 3 ;
int arr[] = new int [] { 8 , 9 , 10 , 11 , 12 };
int n = arr.length;
System.out.println(xorLessK(arr, n, k));
}
}
|
Python3
def xorLessK(arr, n, k):
count = 0
for i in range (n):
tempXor = 0
for j in range (i, n):
tempXor ^ = arr[j]
if (tempXor < k):
count + = 1
return count
if __name__ = = '__main__' :
k = 3
arr = [ 8 , 9 , 10 , 11 , 12 ]
n = len (arr)
print (xorLessK(arr, n, k))
|
C#
using System;
class GFG {
static int xorLessK( int []arr, int n, int k)
{
int count = 0;
for ( int i = 0; i < n; i++) {
int tempXor = 0;
for ( int j = i; j < n; j++) {
tempXor ^= arr[j];
if (tempXor < k)
count++;
}
}
return count;
}
static public void Main ()
{
int k = 3;
int []arr = new int [] {8, 9, 10,
11, 12 };
int n = arr.Length;
Console.WriteLine(xorLessK(arr, n, k));
}
}
|
PHP
<?php
function xorLessK( $arr , $n , $k )
{
$count = 0;
for ( $i = 0; $i < $n ; $i ++)
{
$tempXor = 0;
for ( $j = $i ; $j < $n ; $j ++)
{
$tempXor ^= $arr [ $j ];
if ( $tempXor < $k )
$count ++;
}
}
return $count ;
}
$n ; $k = 3;
$arr = array (8, 9, 10, 11, 12);
$n = count ( $arr );
echo xorLessK( $arr , $n , $k );
?>
|
Javascript
<script>
function xorLessK(arr, n, k)
{
let count = 0;
for (let i = 0; i < n; i++) {
let tempXor = 0;
for (let j = i; j < n; j++) {
tempXor ^= arr[j];
if (tempXor < k)
count++;
}
}
return count;
}
let k = 3;
let arr = [8, 9, 10, 11, 12];
let n = arr.length;
document.write(xorLessK(arr, n, k));
</script>
|
Time Complexity:
.
Space complexity :- O(1)
Efficient Approach: An efficient approach will be to calculate all of the prefix xor values i.e. a[1:i] for all i.
It can be verified that the xor of a subarray a[l:r] can be written as (a[1:l-1] xor a[1:r]), where a[i, j] is the xor of all the elements with index such that, i <= index <= j.
Explanation:
We will store a number as a binary number in trie. The left child will show that the next bit is 0 and the right child will show the next bit is 1.
For example, the given picture below shows numbers 1001 and 1010 in trie.

If xor[i, j] represents the xor of all elements in the subarray a[i, j], then at an index i what we have is, a trie which has xor[1:1], xor[1:2]…..xor[1:i-1] already inserted. Now we somehow count how many of these (numbers in trie) are such that its xor with xor[1:i] is smaller than k. This will cover all the subarrays ending at the index i and having xor i.e. xor[j, i] <=k;
Now the problem remains, how to count the numbers with xor smaller than k. So, for example, take the current bit of the ith index element is p, a current bit of number k be q and the current node in trie be node.
Take the case when p=1, k=1. Then if we go to the right child the current xor would be 0 (as the right child means 1 and p=1, 1(xor)1=0).As k=1, all the numbers that are to the right child of this node would give xor value smaller than k. So, we would count the numbers that are right to this node.
If we go to the left child, the current xor would be 1 (as the left child means 0 and p=1, 0(xor)1=1). So, if we go to the left child we can still find number with xor smaller than k, therefore we move on to the left child.
So, to count the numbers that are below a given node, we modify the trie and each node will also store the number of leafs in that subtree and this would be modified after each insertion.
Other three cases for different values of p and k can be solved in the same way to the count the number of numbers with xor less than k.
Below is the C++ implementation of the above idea:
CPP
#include <iostream>
using namespace std;
class trienode {
public :
int left_count, right_count;
trienode* left;
trienode* right;
trienode()
{
left_count = 0;
right_count = 0;
left = NULL;
right = NULL;
}
};
void insert(trienode* root, int element)
{
for ( int i = 31; i >= 0; i--) {
int x = (element >> i) & 1;
if (x) {
root->right_count++;
if (root->right == NULL)
root->right = new trienode();
root = root->right;
}
else {
root->left_count++;
if (root->left == NULL)
root->left = new trienode();
root = root->left;
}
}
}
int query(trienode* root, int element, int k)
{
if (root == NULL)
return 0;
int res = 0;
for ( int i = 31; i >= 0; i--) {
bool current_bit_of_k = (k >> i) & 1;
bool current_bit_of_element = (element >> i) & 1;
if (current_bit_of_k) {
if (current_bit_of_element) {
res += root->right_count;
if (root->left == NULL)
return res;
root = root->left;
}
else {
res += root->left_count;
if (root->right == NULL)
return res;
root = root->right;
}
}
else {
if (current_bit_of_element) {
if (root->right == NULL)
return res;
root = root->right;
}
else {
if (root->left == NULL)
return res;
root = root->left;
}
}
}
return res;
}
int main()
{
int n = 5, k = 3;
int arr[] = { 8, 9, 10, 11, 12 };
int temp, temp1, temp2 = 0;
trienode* root = new trienode();
insert(root, 0);
long long total = 0;
for ( int i = 0; i < n; i++) {
temp = arr[i];
temp1 = temp2 ^ temp;
total += query(root, temp1, k);
insert(root, temp1);
temp2 = temp1;
}
cout << total << endl;
return 0;
}
|
Java
import java.util.*;
class TrieNode {
int left_count, right_count;
TrieNode left;
TrieNode right;
TrieNode() {
left_count = 0 ;
right_count = 0 ;
left = null ;
right = null ;
}
}
class Main {
static void insert(TrieNode root, int element) {
for ( int i = 31 ; i >= 0 ; i--) {
int x = (element >> i) & 1 ;
if (x == 1 ) {
root.right_count++;
if (root.right == null )
root.right = new TrieNode();
root = root.right;
} else {
root.left_count++;
if (root.left == null )
root.left = new TrieNode();
root = root.left;
}
}
}
static int query(TrieNode root, int element, int k) {
if (root == null )
return 0 ;
int res = 0 ;
for ( int i = 31 ; i >= 0 ; i--) {
int current_bit_of_k = (k >> i) & 1 ;
int current_bit_of_element = (element >> i) & 1 ;
if (current_bit_of_k == 1 ) {
if (current_bit_of_element == 1 ) {
res += root.right_count;
if (root.left == null )
return res;
root = root.left;
}
else {
res += root.left_count;
if (root.right == null )
return res;
root = root.right;
}
}
else {
if (current_bit_of_element == 1 ) {
if (root.right == null )
return res;
root = root.right;
}
else {
if (root.left == null )
return res;
root = root.left;
}
}
}
return res;
}
public static void main(String[] args) {
int n = 5 , k = 3 ;
int [] arr = { 8 , 9 , 10 , 11 , 12 };
int temp, temp1, temp2 = 0 ;
TrieNode root = new TrieNode();
insert(root, 0 );
long total = 0 ;
for ( int i = 0 ; i < n; i++) {
temp = arr[i];
temp1 = temp2 ^ temp;
total += query(root, temp1, k);
insert(root, temp1);
temp2 = temp1;
}
System.out.println(total);
}
}
|
Python3
class TrieNode:
def __init__( self ):
self .left_count = 0
self .right_count = 0
self .left = None
self .right = None
def insert(root, element):
for i in range ( 31 , - 1 , - 1 ):
x = (element >> i) & 1
if x:
root.right_count + = 1
if root.right is None :
root.right = TrieNode()
root = root.right
else :
root.left_count + = 1
if root.left is None :
root.left = TrieNode()
root = root.left
def query(root, element, k):
if root is None :
return 0
res = 0
for i in range ( 31 , - 1 , - 1 ):
current_bit_of_k = (k >> i) & 1
current_bit_of_element = (element >> i) & 1
if current_bit_of_k:
if current_bit_of_element:
res + = root.right_count
if root.left is None :
return res
root = root.left
else :
res + = root.left_count
if root.right is None :
return res
root = root.right
else :
if current_bit_of_element:
if root.right is None :
return res
root = root.right
else :
if root.left is None :
return res
root = root.left
return res
if __name__ = = "__main__" :
n = 5
k = 3
arr = [ 8 , 9 , 10 , 11 , 12 ]
temp = 0
temp1 = 0
temp2 = 0
root = TrieNode()
insert(root, 0 )
total = 0
for i in range (n):
temp = arr[i]
temp1 = temp2 ^ temp
total + = query(root, temp1, k)
insert(root, temp1)
temp2 = temp1
print (total)
|
C#
using System;
public class TrieNode {
public int left_count, right_count;
public TrieNode left;
public TrieNode right;
public TrieNode() {
left_count = 0;
right_count = 0;
left = null ;
right = null ;
}
}
public class MainClass {
public static void Insert(TrieNode root, int element) {
for ( int i = 31; i >= 0; i--) {
int x = (element >> i) & 1;
if (x == 1) {
root.right_count++;
if (root.right == null )
root.right = new TrieNode();
root = root.right;
} else {
root.left_count++;
if (root.left == null )
root.left = new TrieNode();
root = root.left;
}
}
}
public static int Query(TrieNode root, int element, int k) {
if (root == null )
return 0;
int res = 0;
for ( int i = 31; i >= 0; i--) {
int current_bit_of_k = (k >> i) & 1;
int current_bit_of_element = (element >> i) & 1;
if (current_bit_of_k == 1) {
if (current_bit_of_element == 1) {
res += root.right_count;
if (root.left == null )
return res;
root = root.left;
}
else {
res += root.left_count;
if (root.right == null )
return res;
root = root.right;
}
}
else {
if (current_bit_of_element == 1) {
if (root.right == null )
return res;
root = root.right;
}
else {
if (root.left == null )
return res;
root = root.left;
}
}
}
return res;
}
public static void Main( string [] args) {
int n = 5, k = 3;
int [] arr = { 8, 9, 10, 11, 12 };
int temp, temp1, temp2 = 0;
TrieNode root = new TrieNode();
Insert(root, 0);
long total = 0;
for ( int i = 0; i < n; i++) {
temp = arr[i];
temp1 = temp2 ^ temp;
total += Query(root, temp1, k);
Insert(root, temp1);
temp2 = temp1;
}
Console.WriteLine(total);
}
}
|
Javascript
class TrieNode {
constructor(){
this .left_count = 0;
this .right_count = 0;
this .left = null ;
this .right = null ;
}
}
function insert(root, element) {
for (let i = 31; i >= 0; i--) {
let x = (element >> i) & 1;
if (x == 1) {
root.right_count++;
if (root.right == null )
root.right = new TrieNode();
root = root.right;
} else {
root.left_count++;
if (root.left == null )
root.left = new TrieNode();
root = root.left;
}
}
}
function query(root, element, k) {
if (root == null )
return 0;
let res = 0;
for (let i = 31; i >= 0; i--) {
let current_bit_of_k = (k >> i) & 1;
let current_bit_of_element = (element >> i) & 1;
if (current_bit_of_k == 1) {
if (current_bit_of_element == 1) {
res += root.right_count;
if (root.left == null )
return res;
root = root.left;
}
else {
res += root.left_count;
if (root.right == null )
return res;
root = root.right;
}
}
else {
if (current_bit_of_element == 1) {
if (root.right == null )
return res;
root = root.right;
}
else {
if (root.left == null )
return res;
root = root.left;
}
}
}
return res;
}
let n = 5, k = 3;
let arr = [8, 9, 10, 11, 12];
let temp, temp1, temp2 = 0;
let root = new TrieNode();
insert(root, 0);
let total = 0;
for (let i = 0; i < n; i++) {
temp = arr[i];
temp1 = temp2 ^ temp;
total += query(root, temp1, k);
insert(root, temp1);
temp2 = temp1;
}
console.log(total);
|
Time complexity: O(n*log(max)), where max is the maximum element in the array.
The space complexity of the given code depends on the number of nodes in the Trie data structure created by the insert function. Since each node has two pointers (left and right) and two integer values (left_count and right_count), the space complexity can be approximated as O(8Nlog(max_element)), where N is the number of elements in the array and max_element is the maximum value of an element in the array.
Related Articles:
This article is contributed by Amritya Vagmi. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.