Open In App

Find all ranges of consecutive numbers from Array | Set -2 (using Exponential BackOff)

Improve
Improve
Like Article
Like
Save
Share
Report

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) 
 



Last Updated : 31 Jan, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads