找到数字的最短平方和

时间:2015-06-16 16:18:44

标签: algorithm math

查找并输出给定​​数字的最短平方和。

示例:12 = 2^2 + 2^2 + 2^2 (not 3^2 + 1^2 + 1^2 + 1^2)

输出:{2 2 2}

3 个答案:

答案 0 :(得分:7)

这是最小币变化问题,其中硬币为[1,4,9,...,(ceil(sqrt(n)))^2]

可以使用Dynamic Programming (DP)按照递归公式解决:

D(i,0) = 0
D(i,x) = infinity    x<0
D(0,x) = infinity    x>0
D(i,x) = min { D(i,x-i^2) + 1, D(i-1,x) }

在构建矩阵时(假设自下而上的DP),D(ceil(sqrt(n)),n)中矩阵中表示的元素是构建输入数字所需的最小数量的“硬币”(平方数)。

获取实际元素是通过在构建矩阵后跟踪您在矩阵中的选择来完成的,并在每个点检查您是否添加了一个加数。
更详细地解释了this threadthis thread中的类似问题。

答案 1 :(得分:0)

这是问题的视觉基本解决方案。 需要进行编辑以缓存中间答案,以便算法明显更快。目前......只能快速计算出大约40到50的值。这是完全工作和测试。它只返回最短的答案,而其中一个值高于其他值的左侧。

Private Function ShortestSquareSum(x As Integer) As Integer()()
    If x < 0 Then
        Throw New ArgumentException("Parameter cannot be negative.", "x")
    ElseIf x = 0 Then
        Return New Integer()() {New Integer() {}}
    Else
        Dim answers As New List(Of Integer())
        Dim shortest As Integer? = Nothing
        For y As Integer = Math.Floor(Math.Sqrt(x)) To 1 Step -1
            Dim remaining As Integer = x - y * y
            Dim tempAnswers As Integer()() = ShortestSquareSum(x - y * y)
            For Each answer As Integer() In tempAnswers
                Dim currentAnswer As New List(Of Integer)
                currentAnswer.Add(y)
                currentAnswer.AddRange(answer)
                If Not shortest.HasValue OrElse currentAnswer.Count < shortest Then
                    shortest = currentAnswer.Count
                    answers.Clear()
                    answers.Add(currentAnswer.ToArray())
                ElseIf currentAnswer.Count = shortest AndAlso (answer.Count = 0 OrElse y > answer(0)) Then
                    answers.Add(currentAnswer.ToArray())
                End If
            Next
        Next
        Return answers.ToArray()
    End If
End Function

答案 2 :(得分:0)

public static void shortest_square(int n)
{
    int i=2;
    List<Integer> list= new ArrayList<Integer>();
    while(i<=n) || n!=0)
    {
     if(n%(i*i)==0)
     {
      n=n-(i*i);
      list.add(i);
     }
     else
     {
      i++;
     }

    }
    System.out.println(list);
}