从 Array | 中查找所有连续数字范围设置 -2(使用指数退避)
给定一个由N个整数组成且没有任何重复的排序数组arr[] ,任务是从该数组中找到连续数字的范围。
例子:
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
方法一:使用数组遍历的方法已经在本文的 Set 1 中讨论过了。这个想法是从初始位置遍历数组,并且对于数组中的每个元素,检查当前元素和前一个元素之间的差异。
时间复杂度: O(N),其中 N 是数组的长度。
方法 2:指数退避
指数退避是一种算法,它使用任何类型的反馈/事件来成倍地降低某些过程的当前速率。这用于实现可接受/最佳速率。这些算法在广泛的系统和过程中得到使用,其中无线电网络和计算机网络尤其引人注目。
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.
下面是上述方法的实现:
C++
// C++ program to find the ranges of
// consecutive numbers from array
#include
using namespace std;
// Function to find consecutive ranges
vector consecutiveRanges(
int nums[], int len)
{
vector res;
// Start with the first element and
// traverse whole of array
for (int i = 0; i < len;) {
// For each contigous 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 continous intergar 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 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] << ", ";
}
}
Javascript
[1->3, 6->7]
[-1->2, 5->6, 8]
[-1, 3->5, 20->21, 25]
时间复杂度:
Worst Case: O(N)
Average Case: O(log N)
Best Base: O(log N)