当前位置: 面试刷题>> 硬币排成线 (经典算法题500道)


题目描述补充

题目:硬币排成线

给定一个整数数组coins,其中每个元素代表不同面值的硬币。现在,你需要将这些硬币按照某种顺序排列成一条直线,使得从一端到另一端的累加值恰好等于一个给定的目标值target。注意,每个硬币只能使用一次,并且要求找到一种排列方式使得这种累加恰好等于target,同时返回这种排列的索引序列(硬币在数组中的位置,从0开始计数)。

示例输入

  • coins = [1, 2, 5]
  • target = 10

示例输出

  • 可能的输出之一为[0, 2, 1],表示硬币按照1, 5, 2的顺序排列,累加值为1+5+2=8,但这里为了简化,我们假设存在一种排列使得累加值恰好为10(实际上,这个示例的target10时,直接给出的coins无法精确组成10,这里仅为示例说明)。在真实情况中,若无法找到这样的排列,则返回空数组[]null(根据具体语言习惯)。

注意: 题目要求找到一种可能的排列方式,如果存在多种排列,返回任意一种即可。如果不存在任何排列方式使得累加值等于target,则返回空结果。

PHP 示例代码

function findCoinSequence($coins, $target) {
    // 递归函数,尝试所有可能的组合
    function backtrack($start, $remaining, $path, $coins, $target) {
        if ($remaining == 0) {
            // 如果剩余值为0,找到了一个解
            return [$path];
        }
        if ($remaining < 0) {
            // 如果剩余值小于0,此路径无效
            return [];
        }
        
        $results = [];
        for ($i = $start; $i < count($coins); $i++) {
            // 尝试加入当前硬币
            $newPath = $path . $i . ' ';
            $results = array_merge($results, backtrack($i + 1, $remaining - $coins[$i], $newPath, $coins, $target));
        }
        
        // 过滤空结果
        return array_filter($results);
    }

    $result = backtrack(0, $target, '', $coins, $target);
    // 移除尾部空格并分割成数组
    if (!empty($result[0])) {
        return explode(' ', trim($result[0]));
    }
    return [];
}

// 示例用法
$coins = [1, 2, 5];
$target = 10; // 注意:这个target对于给定的coins可能没有解
$sequence = findCoinSequence($coins, $target);
print_r($sequence);

注意: 由于题目给定的示例中target10coins[1, 2, 5]无法精确凑成10,上述代码将展示如何使用回溯法来尝试所有可能的组合。然而,在实际情况中,如果target无法被coins精确凑成,函数将返回空数组。

Python 和 JavaScript 示例

由于篇幅和避免重复,Python 和 JavaScript 的实现将遵循类似的逻辑,但会略有不同,特别是语法和数据结构处理上。你可以基于上述 PHP 示例的逻辑来编写它们。码小课网站中有更多关于回溯算法和相关数据结构的内容,欢迎大家前往学习。

推荐面试题