查找第一个合适的元素数组

时间:2018-08-21 12:37:19

标签: php recursion

我有一种从另一种方法输出的树形结构,格式为:

$tracks = [[1,4],[3,5],[2,3,5],[1,2],[2,4]];

顶部节点为空数组,$tracks[0] = [1,4]合并前两个节点(14)。从$tracks[2] = [2,3,5]看,这不是二叉树,这意味着有三个可能的节点。

我想找到数字不重复的第一个组合(例如[1,3,5,2,4]),因此不需要遍历整棵树。

我创建了一个函数,但是遇到了一个我无法解决的问题:

$availableTracks = [[1,4],[3,5],[2,3,5],[1,2],[2,4]];
$availableTracks2 = [[1,4],[3,5],[2,3,5],[1],[2,4]];


/*
    $pairedTracks = all tracks given
    $currentPath = generated path
    $level = which level in tree
    $nodeElement = element position
    $previousnode = which node it started from in current level
*/

function findBestPath($pairedtracks,$currentPath,$level,$nodeElement,$previousNode){
    if (in_array($pairedtracks[$level][$nodeElement],$currentPath)){
        echo "[IN ARRAY]: Node element in current: ".$pairedtracks[$level][$nodeElement]." on level: ".$level;
        echo "<br>";
        echo "Node which level lowered from: ".$previousNode;
        echo "<br>";
        //Check if node element is in array
        $maxLength = count($pairedtracks[$level]);
        if ($nodeElement+1 == $maxLength){
            //Current was final, return back up
            $level -= 1;
            // Go forward from previous
            $previousNode += 1;
            // Set new start node in recursive function
            $nodeElement = $previousNode;
            if ($nodeElement == count($pairedtracks[$level])){
                //Check if node element is on the same length, then go back even more.
                /*
                    At this point i realized that i'm going to need to keep track of too many previous iterations
                */

            }
            echo "Moving back up to level: ".$level.", starting iteration from: ".$nodeElement;
            echo "<br>";
            // Remove previously added element from that level!
            array_splice($currentPath, $currentPath[count($currentPath)-1], 1);
            return findBestPath($pairedtracks,$currentPath,$level,$nodeElement,$previousNode);
        }
        else {
            //More elements to follow
            $nodeElement += 1;
            return findBestPath($pairedtracks,$currentPath,$level,$nodeElement,$previousNode);
        }

    }
    else {
        //Was not in array, element can be added to current path
        echo "Adding element to current path: ".$pairedtracks[$level][$nodeElement];
        echo "<br>";
        $currentPath[] = $pairedtracks[$level][$nodeElement];
        //Check if path has finalized or check more
        if (count($currentPath) == count($pairedtracks)){
            //Search finished
            return $currentPath;
        }
        else {
            //Move downwards
            $level += 1;
            return findBestPath($pairedtracks,$currentPath,$level,0,$nodeElement);
        }
    }


}

$path = findBestPath($availableTracks2,[],0,0,0);
foreach ($path as &$value) {
    echo $value." ";
}    

它适用于availableTracks,但是在必须返回多个级别时会遇到问题。我得出的结论是,我需要保留多个previousnode,但我确信应该可以不将其保留在内存中,而只需按照每次递归修改数组的长度即可。不幸的是,我想不出办法,也许有人可以帮我解决这个问题?

1 个答案:

答案 0 :(得分:0)

不确定为什么我没有任何评论就被否决了,但是我认为我设法解决了这个问题:

$availableTracks = [[1,4],[3,5],[2,3,5],[1,2],[2,4]];
$availableTracks2 = [[1,4],[3,5],[2,3,5],[1],[2,4]];


function findBestPath($pairedtracks,$currentPath,$level,$nodeElement,$previousNode){
    $maxLength = count($pairedtracks[$level]);
    if ($nodeElement == $maxLength){
        echo "[Back up more]<br>";
        echo "Current pair: [";
        foreach ($pairedtracks[$level] as &$pairElement){
            echo $pairElement.",";
        }
        echo "]<br>";
        echo "Current path: [";
        foreach ($currentPath as &$pathElement){
            echo $pathElement.",";
        }
        echo "]<br>";
        //Current was final, return back up
        $level -= 1;
        $lastInserted = $currentPath[count($currentPath)-1];
        //Take index from previous level
        $indexNumber = 0;
        foreach ($pairedtracks[$level] as &$pairElement){
            echo "Pair: ".$pairElement."<br>";
            if ($pairElement == $lastInserted){
                break;
            }
            $indexNumber += 1;
        }
        echo "Previous element was on index ".$indexNumber."<br>";
        $nodeElement = $indexNumber+1;
        echo "Moving back up to level: ".$level.", starting iteration from: ".$nodeElement.", removed element: ".$currentPath[count($currentPath)-1];
        echo "<br>";
        // Remove previously added element from that level!
        array_splice($currentPath, count($currentPath)-1, 1);
        return findBestPath($pairedtracks,$currentPath,$level,$nodeElement,$previousNode);  
    }
    else if (in_array($pairedtracks[$level][$nodeElement],$currentPath)){
        echo "[IN ARRAY]: Node element in current: ".$pairedtracks[$level][$nodeElement]." on level: ".$level;
        echo "<br>";
        //Check if node element is in array

        if ($nodeElement+1 >= $maxLength){
            //Current was final, return back up
            $level -= 1;
            $lastInserted = $currentPath[count($currentPath)-1];
            //Take index from previous level
            $indexNumber = 0;
            foreach ($pairedtracks[$level] as &$pairElement){
                if ($pairElement == $lastInserted){
                    break;
                }
                $indexNumber += 1;
            }
            echo "Previous element was on index ".$indexNumber."<br>";
            $nodeElement = $indexNumber+1;
            echo "Moving back up to level: ".$level.", starting iteration from: ".$nodeElement.", removed element: ".$currentPath[count($currentPath)-1];
            echo "<br>";
            // Remove previously added element from that level!
            array_splice($currentPath, count($currentPath)-1, 1);
            return findBestPath($pairedtracks,$currentPath,$level,$nodeElement,$previousNode);
        }
        else {
            //More elements to follow
            $nodeElement += 1;
            return findBestPath($pairedtracks,$currentPath,$level,$nodeElement,$previousNode);
        }

    }
    else {
        //Was not in array, element can be added to current path
        echo "Adding element to current path: ".$pairedtracks[$level][$nodeElement];
        echo "<br>";
        $currentPath[] = $pairedtracks[$level][$nodeElement];
        //Check if path has finalized or check more
        if (count($currentPath) == count($pairedtracks)){
            //Search finished
            return $currentPath;
        }
        else {
            //Move downwards
            $level += 1;
            return findBestPath($pairedtracks,$currentPath,$level,0,$nodeElement);
        }
    }


}

$path = findBestPath($availableTracks,[],0,0,0);
foreach ($path as &$value) {
    echo $value." ";
}

我使用currentPath作为存储工具。在返回上一级之前,我在currentPath中使用了最后一个元素(移回顶部时将其删除),并检查它在上一级的索引是什么。然后,我从该索引开始迭代(因为以前的索引已经完成)。