Find all ranges of consecutive numbers from Array | Set -2 (using Exponential BackOff)
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 -> 7Input: 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> |
[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)
Please Login to comment...