Find all ranges of consecutive numbers from Array | Set -2 (using Exponential BackOff)
Last Updated :
31 Jan, 2023
Given a sorted array arr[] consisting of N integers without any duplicates, the task is to find the ranges of consecutive numbers from that array.
Examples:
Input: arr[] = {1, 2, 3, 6, 7}
Output: 1->3, 6->7
Explanation: There are two ranges of consecutive number from that array.
Range 1 = 1 -> 3
Range 2 = 6 -> 7
Input: arr[] = {-1, 0, 1, 2, 5, 6, 8}
Output: -1->2, 5->6, 8
Explanation: There are three ranges of consecutive number from that array.
Range 1 = -1 -> 2
Range 2 = 5 -> 6
Range 3 = 8
Approach 1: The approach using traversal of array has been discussed in Set 1 of this article. The idea is to traverse the array from the initial position and for every element in the array, check the difference between the current element and the previous element.
Time Complexity: O(N), where N is the length of the array.
Approach 2: Exponential Back-off
Exponential backoff is an algorithm that uses any sort of feedback/event to multiplicatively decrease the current rate of some process. This is used to achieve an acceptable/optimum rate. These algorithms find usage in a wide range of systems and processes, with radio networks and computer networks being particularly notable.
Instead of using linear incremental approach we will use exponential backoff as following:
- Fix your rate as exponential increment(i = i*2) instead of linear increment (i ++)
- At the exit condition (nums[i] - nums[0] != i), do the linear incremental in last half of the interval. i.e. ( i/2 -> i) instead of doing it for 0 to i.
This will help you achieve the optimal solution very fast as compared to linear incremental solution, because the nature of solution is exponential at many times in average case.

Below is the implementation of the above approach:
C++
// C++ program to find the ranges of
// consecutive numbers from array
#include <bits/stdc++.h>
using namespace std;
// Function to find consecutive ranges
vector<string> consecutiveRanges(
int nums[], int len)
{
vector<string> res;
// Start with the first element and
// traverse whole of array
for (int i = 0; i < len;) {
// For each continuous integers subarray
// check the first two elements
int j = i + 1;
int l = 1;
// Point of break is either out of bound
// or break of continuous integer range
while (j < len
&& nums[i] + (j - i) == nums[j]) {
// increase the interval/range
// by 2 (exponential)
l *= 2;
j = i + l;
}
// if only one element in range
// directly push in result
if (j - i == 1) {
res.push_back(to_string(nums[i]));
}
else {
// do the linear incremental
// in last half of the interval
j = j - (l / 2);
while (j < len
&& nums[i] + (j - i) == nums[j]) {
j++;
}
// push the range to result
res.push_back(to_string(nums[i]) + "->"
+ to_string(nums[j - 1]));
}
i = j;
}
return res;
}
// Driver Code.
int main()
{
// Test Case 1:
int arr1[] = { 1, 2, 3, 6, 7 };
int n = sizeof(arr1) / sizeof(arr1[0]);
vector<string> ans = consecutiveRanges(arr1, n);
cout << "[";
for (int i = 0; i < ans.size(); i++) {
if (i == ans.size() - 1)
cout << ans[i] << "]" << endl;
else
cout << ans[i] << ", ";
}
// Test Case 2:
int arr2[] = { -1, 0, 1, 2, 5, 6, 8 };
n = sizeof(arr2) / sizeof(arr2[0]);
ans = consecutiveRanges(arr2, n);
cout << "[";
for (int i = 0; i < ans.size(); i++) {
if (i == ans.size() - 1)
cout << ans[i] << "]" << endl;
else
cout << ans[i] << ", ";
}
// Test Case 3:
int arr3[] = { -1, 3, 4, 5, 20, 21, 25 };
n = sizeof(arr3) / sizeof(arr3[0]);
ans = consecutiveRanges(arr3, n);
cout << "[";
for (int i = 0; i < ans.size(); i++) {
if (i == ans.size() - 1)
cout << ans[i] << "]" << endl;
else
cout << ans[i] << ", ";
}
}
Java
// Java program to find the ranges of
// consecutive numbers from array
import java.util.*;
class GFG {
// Function to find consecutive ranges
static List<String> consecutiveRanges(
int[] nums, int len)
{
List<String> res
= new ArrayList<String>();
// Start with the first element and
// traverse whole of array
for (int i = 0; i < len;) {
// For each continuous integers subarray
// check the first two elements
int j = i + 1;
int l = 1;
// Point of break is either out of bound
// or break of continuous integer range
while (j < len
&& nums[i] + (j - i) == nums[j]) {
// increase the interval/range
// by 2 (exponential)
l *= 2;
j = i + l;
}
// if only one element in range
// directly push in result
if (j - i == 1) {
res.add(String.valueOf(nums[i]));
}
else {
// do the linear incremental
// in last half of the interval
j = j - (l / 2);
while (j < len
&& nums[i] + (j - i) == nums[j]) {
j++;
}
// push the range to result
res.add(String.valueOf(nums[i]) + "->"
+ String.valueOf(nums[j - 1]));
}
i = j;
}
return res;
}
// Driver Code.
public static void main(String args[])
{
// Test Case 1:
int[] arr1 = { 1, 2, 3, 6, 7 };
int n = arr1.length;
List<String> ans = new ArrayList<String>();
ans = consecutiveRanges(arr1, n);
System.out.print(ans);
System.out.println();
// Test Case 2:
int[] arr2 = { -1, 0, 1, 2, 5, 6, 8 };
n = arr2.length;
ans = consecutiveRanges(arr2, n);
System.out.print(ans);
System.out.println();
// Test Case 3:
int[] arr3 = { -1, 3, 4, 5, 20, 21, 25 };
n = arr3.length;
ans = consecutiveRanges(arr3, n);
System.out.print(ans);
System.out.println();
}
}
// This code is contributed by pushpeshrajdx01
Python3
## Function to find consecutive ranges
def consecutiveRanges(nums, length):
res = []
## Start with the first element and
## traverse whole of array
i = 0
while i < length:
## For each continuous integers subarray
## check the first two elements
j = i + 1
l = 1
## Point of break is either out of bound
## or break of continuous integer range
while (j < length and ((nums[i] + (j - i)) == nums[j])):
## increase the interval/range
## by 2 (exponential)
l *= 2;
j = i + l;
## if only one element in range
## directly push in result
if (j - i == 1):
res.append(str(nums[i]))
else:
## do the linear incremental
## in last half of the interval
j = j - (l // 2);
while (j < length and ((nums[i] + (j - i)) == nums[j])):
j+=1
## push the range to result
res.append(str(nums[i]) + "->" + str(nums[j - 1]))
i = j
return res
## Driver code
if __name__=='__main__':
## Test Case 1:
arr1 = [1, 2, 3, 6, 7]
n = len(arr1)
ans = consecutiveRanges(arr1, n)
print("[",end='')
for i in range(len(ans)):
if(i==len(ans)-1):
print(ans[i], end='')
print("]")
else:
print(ans[i], end='')
print(", ", end='')
## Test Case 2:
arr2 = [-1, 0, 1, 2, 5, 6, 8]
n = len(arr2)
ans = consecutiveRanges(arr2, n)
print("[",end='')
for i in range(len(ans)):
if(i==len(ans)-1):
print(ans[i], end='')
print("]")
else:
print(ans[i], end='')
print(", ", end='')
## Test Case 3:
arr3 = [-1, 3, 4, 5, 20, 21, 25]
n = len(arr3)
ans = consecutiveRanges(arr3, n)
print("[",end='')
for i in range(len(ans)):
if(i==len(ans)-1):
print(ans[i], end='')
print("]")
else:
print(ans[i], end='')
print(", ", end='')
# This code is contributed by subhamgoyal2014.
C#
// C# program to implement above approach
using System;
using System.Collections.Generic;
class GFG
{
// Function to find consecutive ranges
static List<string> consecutiveRanges(int[] nums, int len)
{
List<string> res = new List<string>();
// Start with the first element and
// traverse whole of array
for (int i = 0 ; i < len ; ) {
// For each continuous integers subarray
// check the first two elements
int j = i + 1;
int l = 1;
// Point of break is either out of bound
// or break of continuous integer range
while (j < len && nums[i] + (j - i) == nums[j]) {
// increase the interval/range
// by 2 (exponential)
l *= 2;
j = i + l;
}
// if only one element in range
// directly push in result
if (j - i == 1) {
res.Add(nums[i].ToString());
}
else {
// do the linear incremental
// in last half of the interval
j = j - (l / 2);
while (j < len
&& nums[i] + (j - i) == nums[j]) {
j++;
}
// push the range to result
res.Add(nums[i].ToString() + "->"
+ nums[j - 1].ToString());
}
i = j;
}
return res;
}
// Driver Code
public static void Main(string[] args)
{
// Test Case 1:
int[] arr1 = { 1, 2, 3, 6, 7 };
int n = arr1.Length;
List<string> ans = consecutiveRanges(arr1, n);
Console.Write("[");
for (int i = 0 ; i < ans.Count ; i++) {
if (i == ans.Count - 1)
Console.Write(ans[i] + "]\n");
else
Console.Write(ans[i] + ", ");
}
// Test Case 2:
int[] arr2 = { -1, 0, 1, 2, 5, 6, 8 };
n = arr2.Length;
ans = consecutiveRanges(arr2, n);
Console.Write("[");
for (int i = 0 ; i < ans.Count ; i++) {
if (i == ans.Count - 1)
Console.Write(ans[i] + "]\n");
else
Console.Write(ans[i] + ", ");
}
// Test Case 3:
int[] arr3 = { -1, 3, 4, 5, 20, 21, 25 };
n = arr3.Length;
ans = consecutiveRanges(arr3, n);
Console.Write("[");
for (int i = 0 ; i < ans.Count ; i++) {
if (i == ans.Count - 1)
Console.Write(ans[i] + "]\n");
else
Console.Write(ans[i] + ", ");
}
}
}
// This code is contributed by entertain2022.
JavaScript
<script>
// JavaScript program to find the ranges of
// consecutive numbers from array
// Function to find consecutive ranges
const consecutiveRanges = (nums, len) => {
let res = [];
// Start with the first element and
// traverse whole of array
for (let i = 0; i < len;) {
// For each continuous integers subarray
// check the first two elements
let j = i + 1;
let l = 1;
// Point of break is either out of bound
// or break of continuous integer range
while (j < len
&& nums[i] + (j - i) == nums[j]) {
// increase the interval/range
// by 2 (exponential)
l *= 2;
j = i + l;
}
// if only one element in range
// directly push in result
if (j - i == 1) {
res.push(nums[i].toString());
}
else {
// do the linear incremental
// in last half of the interval
j = j - (l / 2);
while (j < len
&& nums[i] + (j - i) == nums[j]) {
j++;
}
// push the range to result
res.push(nums[i].toString() + "->" + nums[j - 1].toString());
}
i = j;
}
return res;
}
// Driver Code.
// Test Case 1:
let arr1 = [1, 2, 3, 6, 7];
let n = arr1.length;
let ans = consecutiveRanges(arr1, n);
document.write("[");
for (let i = 0; i < ans.length; i++) {
if (i == ans.length - 1)
document.write(`${ans[i]}]<br/>`);
else
document.write(`${ans[i]}, `);
}
// Test Case 2:
let arr2 = [-1, 0, 1, 2, 5, 6, 8];
n = arr2.length;
ans = consecutiveRanges(arr2, n);
document.write("[");
for (let i = 0; i < ans.length; i++) {
if (i == ans.length - 1)
document.write(`${ans[i]}]<br/>`);
else
document.write(`${ans[i]}, `);
}
// Test Case 3:
let arr3 = [-1, 3, 4, 5, 20, 21, 25];
n = arr3.length;
ans = consecutiveRanges(arr3, n);
document.write("[");
for (let i = 0; i < ans.length; i++) {
if (i == ans.length - 1)
document.write(`${ans[i]}]<br/>`);
else
document.write(`${ans[i]}, `);
}
// This code is contributed by rakeshsahni
</script>
Output[1->3, 6->7]
[-1->2, 5->6, 8]
[-1, 3->5, 20->21, 25]
Time complexity:
Worst Case: O(N)
Average Case: O(log N)
Best Base: O(log N)
Auxiliary Space: O(N)
Similar Reads
Computer Science Subjects