我正在寻找针对以下问题的JavaScript实现。
考虑一个排序数组:
[1,2,5,9,10,12,20,21,22,23,24,26,27]
我想计算增加1的最大范围的长度,不允许重复。
给定示例具有以下范围:
1,2
9,10
20,21,22,23,24 // the maximum range
26,27
因此给定示例的返回值应为5。
我知道如何用明显的解决方案解决这个问题,但我相信有可能用更有效和更短的算法来解决这个问题。
答案 0 :(得分:2)
我认为这不比其他人所建议的更有效,但代码相当短,并且只在数组上循环一次,除了第一个元素。不确定是否有任何帮助:
var arr = [1, 2, 5, 9, 10, 12, 20, 21, 22, 23, 24, 26, 27];
var streak = 0, best = 0, bestStart;
for (var i = 1; i < arr.length; i++) {
if(arr[i]-arr[i-1] === 1) streak++;
else streak = 0;
if (streak > best) [best, bestStart] = [streak, i - streak];
}
var bestArr = arr.slice(bestStart, bestStart + best + 1);
console.log('Best streak: '+bestArr);
在查看代码之后,我意识到有一种方法可以根据先前的best
值检查数组的最后几个元素来略微加快速度:
var arr = [1, 2, 5, 9, 10, 12, 20, 21, 22, 23, 24, 26, 27];
var streak = 0, best = 0, bestStart;
for (var i = 1; i < arr.length; i++) {
if(best > arr.length - i + streak) break;
if(arr[i]-arr[i-1] === 1) streak++;
else streak = 0;
if (streak > best) [best, bestStart] = [streak, i - streak];
}
var bestArr = arr.slice(bestStart, bestStart + best + 1);
console.log('Best streak: '+bestArr);
答案 1 :(得分:0)
一种可能的解决方案是迭代数组,保持当前范围,只要数字是后继数。如果下一个数字不是前一个数字的后继数,则关闭当前范围并存储其长度 - 将其与最后一个数字的长度进行比较。
在这种方法中,数组只迭代一次,并且范围的最大找到长度在恒定时间内更新,产生O(n)
算法,其中n
是输入中元素的数量。
类似C#的伪代码的实现可以如下。
int MaximumLength = minus infinity
int CurrentValue = Input[0];
int CurrentLength = 1;
for(int i = 1; i < Input.Length; i++)
{
if ( CurrentValue + 1 == Input[i] )
{
// same range
CurrentLength = CurrentLength + 1;
}
else
{
// new range
MaximumLength = Math.Max(MaximumLength, CurrentLength);
CurrentLength = 1;
}
CurrentValue = Input[i];
}
// check current length again after loop termination
MaximumLength = Math.Max(MaximumLength, CurrentLength);
不可能获得比O(n)
更好的效果,因为输入不能在O(n)
时间内读取。如果可能的话,那就意味着有些实例的结果不依赖于输入的每个元素,而对于给定的问题则不然。如果最大范围长度为1,则下面草拟的算法Philipp Maurer也将生成O(n)
运行时绑定,即输入中没有相邻数字是后继数。
答案 2 :(得分:0)
这样的事情应该首先找到最大长度而不是最后长度。
Let max = 0
Let n = array length
While n > 2
Let m = 0
While m <= (array length - n)
Let first = m
Let last = m + n - 1
Let diff = (value of element 'last' in array) - (value of element 'first' in array)
if diff = n - 1 then
max = n
stop
end if
Increase m
end while
Decrease n
end while
修改(javascript实施)
var a = [1,2,5,9,10,12,20,21,22,23,24,26,27];
var max = 1;
var n = a.length;
while(n > 2) {
var m = 0;
while(m <= a.length - n)
{
var first = m;
var last = m + n - 1;
var diff = a[last] - a[first];
if (diff == n - 1 && diff > max) {
max = n;
break;
}
m++;
}
n--;
}
console.log(max);
答案 3 :(得分:0)
我认为循环并与存储的先前最大长度进行比较是最佳解决方案。也许是这样的:
function findLongestRange(input) {
let maxLength = 0
let currentLength = 0
for (let i = 0; i < input.length; i++) {
if (i !== input.length) {
if (input[i] === input[i + 1] - 1) {
currentLength++
} else {
if (maxLength <= currentLength && currentLength !== 0) {
maxLength = currentLength + 1
}
currentLength = 0
}
}
}
return maxLength
}
const data = [1, 2, 5, 9, 10, 12, 20, 21, 22, 23, 24, 26, 27]
console.log(findLongestRange(data))
这是带有测试的版本,用于检查它与不同输入的工作方式。
const data = [1, 2, 5, 9, 10, 12, 20, 21, 22, 23, 24, 26, 27]
function findLongestRange(input) {
let maxLength = 0
let currentLength = 0
for (let i = 0; i < input.length; i++) {
if (i !== input.length) {
if (input[i] === input[i + 1] - 1) {
currentLength++
} else {
if (maxLength <= currentLength && currentLength !== 0) {
maxLength = currentLength + 1
}
currentLength = 0
}
}
}
return maxLength
}
console.clear()
;[
[[1,2,5,6,7,1,2], 3],
[[], 0],
[data, 5],
[[1,2,3], 3],
[[1,3,4,6,8,1], 2],
[[1,3,5], 0],
].forEach((test, index) => {
const result = findLongestRange(test[0])
console.assert(result === test[1], `Fail #${index}: Exp: ${test[1]}, got ${result}`)
})
答案 4 :(得分:-1)
Python回答:
l = [1,2,5,9,10,12,20,21,22,23,24,26,27]
current_range = None
current_range_val = 0
max_range = 0
max_range_val = 0
for i, j in zip(l, l[1:]):
if j - i == 1:
current_range_val += 1
if current_range is None:
current_range = (i, j)
current_range = (current_range[0], j)
else:
if current_range_val > max_range_val:
max_range = current_range
max_range_val = current_range_val
current_range_val = 0
current_range = (j, None)
print(max_range)
给出
(20, 24)