[英]undefined is returned from function
我正在研究二进制搜索,这是我想到的第一件事:
function letsGoBinary(firstArray,array,search){
const middle = Math.floor(array.length / 2);
if(search === array[middle]) {
const rv = firstArray.indexOf(array[middle]);
return rv
}else if(search < array[middle]){
var lowerArray = []
for(var i = 0; i < middle; i++){
lowerArray.push(array[i])
}
letsGoBinary(firstArray,lowerArray, search)
}else if(search > array[middle]){
var forwardArray = []
for(var i = middle + 1; i < array.length; i++){
forwardArray.push(array[i]);
}
letsGoBinary(firstArray,forwardArray,search)
}else {
return -1
}
}
console.log(letsGoBinary([1,4,7,14,16],[1,4,7,14,16], 4))
如果我在第一个 if 语句( search === array[middle]
)中添加console.log()
并记录它记录确切值的rv
,如果我在 else 语句中not found
log 也会发生同样的情况,它会记录但同时日志记录letsGoBinary
其值未定义。 我该如何解决?
在进行递归调用的情况下,您需要返回结果。
return letsGoBinary(firstArray,lowerArray, search);
除了您的问题,请检查切片方法的工作原理,循环不是获取数组一部分的必要条件
这段代码也有点无意义,如果你使用
const rv = firstArray.indexOf(array[middle])
那为什么刚开始不使用
const rv = firstArray.indexOf(search)
这行代码使您所有的二分搜索变得毫无意义,因为它会一个一个地搜索元素
有非常简单的解决方案
function letsGoBinary(array, search){
let start = 0
let end = array.length - 1
while (start <= end) {
const middle = Math.floor((start + end) / 2)
if(search === array[middle]) {
return middle
} else if (search < array[middle]) {
end = middle - 1
} else {
start = middle + 1
}
}
return -1
}
在处理递归函数时,您应该了解基本情况,然后当您想要执行递归调用时,您不仅要再次调用该函数,而且还应该返回该函数作为响应。 例如,如果搜索编号存在于lowerArray 中,则意味着您应该返回letsGoBinary(firstArray,lowerArray, search) 作为答案。
我更新了您的代码,就是这样:注意:查看第 11 行和第 17 行
function letsGoBinary(firstArray,array,search){ const middle = Math.floor(array.length / 2); if(search === array[middle]) { const rv = firstArray.indexOf(array[middle]); return rv }else if(search < array[middle]){ var lowerArray = [] for(var i = 0; i < middle; i++){ lowerArray.push(array[i]) } return letsGoBinary(firstArray,lowerArray, search) }else if(search > array[middle]){ var forwardArray = [] for(var i = middle + 1; i < array.length; i++){ forwardArray.push(array[i]); } return letsGoBinary(firstArray,forwardArray,search) }else { return -1 } } console.log(letsGoBinary([1,4,7,14,16],[1,4,7,14,16], 4))
发生这种情况是因为在第一次执行 search === array[middle] 后,它完全从letsGoBinary 函数返回,因此您必须添加另一个返回语句,请参阅以下代码片段:
function letsGoBinary(firstArray,array,search){
const middle = Math.floor(array.length / 2);
if(search === array[middle]) {
const rv = firstArray.indexOf(array[middle]);
return rv
}else if(search < array[middle]){
var lowerArray = []
for(var i = 0; i < middle; i++){
lowerArray.push(array[i])
}
return letsGoBinary(firstArray,lowerArray, search)
}else if(search > array[middle]){
var forwardArray = []
for(var i = middle + 1; i < array.length; i++){
forwardArray.push(array[i]);
}
return letsGoBinary(firstArray,forwardArray,search)
}else {
return -1
}
}
console.log(letsGoBinary([1,4,7,14,16],[1,4,7,14,16], 4))
Dmitry Reutov 的回答很棒。 如果您更喜欢递归版本,这是一种类似的方法,但使用递归而不是while
循环:
const letsGoBinary = ( sortedArray, value, start = 0, end = sortedArray .length - 1, middle = Math.floor ((end + start) / 2) ) => start > end ? -1 : sortedArray [middle] == value ? middle : sortedArray [middle] < value ? letsGoBinary (sortedArray, value, middle + 1, end) : letsGoBinary (sortedArray, value, start, middle - 1) console .log ( letsGoBinary ([1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233], 34) )
这两种解决方案都只使用一个数组,依靠start
、 end
和middle
索引来跟踪当前搜索位置。
此版本默认在第一次调用时start
和end
,然后在后续搜索中传递它们。 middle
在每次调用时计算为start
和end
之间最接近的整数中点。
对于此示例,第一次调用使用0
和12
start
和end
,使middle
6
,我们正在测试的值将是sortedArray[6]
,即13
。 这小于34
的搜索值,所以我们再次调用7
和12
,这使得middle
变成9
和测试值55
。 这比34
所以我们用7
和8
调用, middle
7
,测试值21
。 那个小于我们的值,我们又用start
和end
都调用了一个8
,这给了我们一个middle
值8
和一个测试值34
。 由于这等于我们的价值,我们返回8
。 如果我们错过了 - 也许我们正在搜索35
- 那么我们将再次调用9
start
和8
end
,并返回-1
,因为start
> end
。 或者,如果我们一直在搜索33
,我们将有8
start
和7
end
,结果相同-1
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.