当前位置: 面试刷题>> 将火柴摆放成正方形 (经典算法题500道)


完整题目描述

题目:将火柴摆放成正方形

假设你有一系列的火柴棒,每根火柴棒的长度相同。现在,你希望用这些火柴棒摆放成尽可能多的边长相等的正方形(正方形之间可以共用火柴棒,但不能折断火柴棒)。给定一个整数 n,代表你拥有的火柴棒总数,请编写一个程序来找出可以摆放成的最大正方形数量以及每个正方形的边长。

注意

  1. 如果无法摆放成任何正方形,则输出最大正方形数量为0,边长任意(通常可以视为0或-1表示无效)。
  2. 如果能摆放成正方形,请按照正方形边长从大到小的顺序输出每个正方形的边长及数量,边长相同的正方形算作一个。

示例

输入n = 12

输出

2 3
1 4

解释:可以用12根火柴棒摆放成2个边长为3的正方形,或者1个边长为4的正方形和4根剩余的火柴棒(但剩余的4根不能构成新的正方形,所以不计入最大正方形数量中)。按照边长从大到小排序,首先输出边长为3的正方形2个,然后输出边长为4的正方形1个(但注意,实际上选择边长为3的正方形方案更优,因为用尽了所有火柴棒)。

PHP 示例代码

function maxSquaresWithMatches($n) {
    $maxSquares = 0;
    $squareSizes = [];

    for ($sideLength = sqrt($n); $sideLength > 0; $sideLength--) {
        if ($n % $sideLength == 0) {
            $numSquares = intdiv($n, $sideLength);
            $maxSquares = max($maxSquares, $numSquares);
            $squareSizes[$sideLength] = $numSquares;
            $n -= $numSquares * $sideLength; // 减去已用火柴棒
        }
    }

    // 按边长从大到小排序并输出结果(由于PHP关联数组保持插入顺序,这里直接输出)
    krsort($squareSizes);
    foreach ($squareSizes as $side => $count) {
        if ($count > 0) { // 只输出数量大于0的边长
            echo "$count $side\n";
        }
    }
    
    // 如果最大正方形数量为0,则特别输出
    if ($maxSquares == 0) {
        echo "0 -1"; // 假设边长-1表示无效
    }
}

// 测试
maxSquaresWithMatches(12);

Python 示例代码

def max_squares_with_matches(n):
    max_squares = 0
    square_sizes = {}

    for side_length in range(int(n**0.5), 0, -1):
        if n % side_length == 0:
            num_squares = n // side_length
            max_squares = max(max_squares, num_squares)
            square_sizes[side_length] = num_squares
            n -= num_squares * side_length

    # 按边长从大到小排序并输出结果
    for side, count in sorted(square_sizes.items(), reverse=True):
        if count > 0:
            print(f"{count} {side}")

    # 如果最大正方形数量为0,则特别输出
    if max_squares == 0:
        print("0 -1")

# 测试
max_squares_with_matches(12)

JavaScript 示例代码

function maxSquaresWithMatches(n) {
    let maxSquares = 0;
    const squareSizes = {};

    for (let sideLength = Math.floor(Math.sqrt(n)); sideLength > 0; sideLength--) {
        if (n % sideLength === 0) {
            const numSquares = Math.floor(n / sideLength);
            maxSquares = Math.max(maxSquares, numSquares);
            squareSizes[sideLength] = numSquares;
            n -= numSquares * sideLength;
        }
    }

    // 按边长从大到小排序并输出结果
    Object.keys(squareSizes).sort((a, b) => b - a).forEach(side => {
        const count = squareSizes[side];
        if (count > 0) {
            console.log(`${count} ${side}`);
        }
    });

    // 如果最大正方形数量为0,则特别输出
    if (maxSquares === 0) {
        console.log("0 -1");
    }
}

// 测试
maxSquaresWithMatches(12);

码小课:在解决此类问题时,理解题目要求和逻辑是关键。通过遍历可能的边长并计算可以摆放的正方形数量,我们可以有效地解决问题。在码小课网站上,你可以找到更多类似的算法题和详细的解题思路,帮助你更好地掌握编程和算法知识。

推荐面试题