2015-08-28 226 views
1

我有一个算法来查找所有foods数组的唯一组合。如果任何组合符合我们的calories value那么它应该返回true。PHP函数'返回'不返回值

这里是我的方法:

<?php 

$food = [ 
    ['a', 70], 
    ['b', 5], 
    ['c', 20], 
    ['d', 10] 
]; 

function eat($calories, $food, $k = 0, $p = []) { 

    for ($i=$k; $i < count($food); $i++) { 

     $r = array_merge($p, [$i]); 

     $c = 0; 
     foreach ($r as $j) { 
      $c += $food[$j][1]; 
     } 

     if ($c == $calories) { 
      echo "success"; 
      return true; 
     } 

     eat($calories, $food, $i+1, $r); 
    } 
} 

var_dump(eat(100, $food)); 

?> 

的问题是:为什么这段代码输出“成功”,但不会返回true?

这里是在线执行:

http://codepad.viper-7.com/PnTEKo

+3

你的函数以递归方式调用它自己,但是永远不会传回以前的返回值。 – mario

+0

我该如何解决这个问题?这个算法的时间复杂度是多少?这比使用按位运算符的组合更好吗? – whyguy

+0

那么谁写了那段代码? (用算法复杂度扩大你的问题并询问替代方法有点宽泛)。解决方案真的取决于它应该如何表现。至少保存以前的'$ success = eat(...);'递归结果。要么过早返回true,要么保持它直到循环之后,然后“返回”它。 – mario

回答

1

你打电话从来没有原来的函数返回true,就叫做返回true,以它的“父母”的后续funtion,但真的是再也没有回到原来的调用者。修复程序将如下所示:

if (eat($calories, $food, $i+1, $r)) { 
    return true; 
} 

该检查什么递归函数返回值,若true,返回在递归阵列功能true再次

+0

现在我明白了。任何有关时间复杂性和替代解决方案的更多信息?谢谢! – whyguy

1

您递归调用的函数。转储的值将是第一个调用的返回值,因为您忽略了其他调用的返回值。

在这里,你似乎只需要达到一个成功的调用,之后该功能必须终止。因此,您可以检查是否成功,如果发生了,则返回true,以防止该函数进一步发送,并告诉调用方(这可以是第一个调用,或者是递归中的其他调用),调用成功。

<?php 

$food = [ 
    ['a', 70], 
    ['b', 5], 
    ['c', 20], 
    ['d', 10] 
]; 

function eat($calories, $food, $k = 0, $p = []) { 

    for ($i=$k; $i < count($food); $i++) { 

     $r = array_merge($p, [$i]); 

     $c = 0; 
     foreach ($r as $j) { 
      $c += $food[$j][1]; 
     } 

     if ($c == $calories) { 
      echo "success"; 
      return true; 
     } 

     if(eat($calories, $food, $i+1, $r)) 
      return true; 
    } 
} 

var_dump(eat(100, $food)); 

?> 
+3

这可能会回答这个问题,但是你没有解释你做了什么。所以这个答案对于未来的读者 – KhorneHoly

+0

并不是非常有用,我编辑了一下并稍加解释。 – Ahmad

1

一个稍微不同的看法是使用内置的函数arrayIterator。

 $food = array(
      'a'=> 70, 
      'b'=> 5, 
      'c'=> 20, 
      'd'=> 10, 
      'e'=> 99 
     ); 

     function eat($calories, $food, $p=array()){ 
      $a = new ArrayObject(array_merge($food, $p)); 
      $iterator = $a->getIterator(); 
      while($iterator->valid()) { 
       if($iterator->current()==$calories) { 
        echo 'success: key='.$iterator->key().' value='.$iterator->current(); 
        return true; 
       } 
       $iterator->next(); 
      } 
      return false; 
     } 

     eat(120, $food, array('banana'=>500,'apple'=>120));