2015-08-28 217 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));