📜  给定数组的最大子序列和为完美平方

📅  最后修改于: 2021-04-29 15:15:02             🧑  作者: Mango

给定一个数组arr [] ,任务是要找到一个形成完美平方的子序列。如果有多个子序列的和等于理想平方,则打印最大和。
解释:

天真的方法:生成给定数组的所有可能的子序列,对于每个子序列,检查其和是否为Perfect Square 。如果找到了这样的总和,请更新最大总和。最后,打印获得的最大金额。
时间复杂度: O(N * 2 N )
辅助空间: O(N)

高效方法:
可以通过使用动态编程方法来优化上述方法。
请按照以下步骤操作:

  • 计算数组的总和
  • 在[√sum,0]范围内迭代k并检查与该和k 2是否存在任何子序列。对于每k ,请执行以下步骤:
    • 初始化尺寸为N * sum的布尔矩阵subset [] [] ,其中sum表示k 2的当前值。
    • subset [i] [j]表示是否存在大小为i且总和为j的子序列。
    • subset [] []的第一列和第一行分别初始化为true和false。
    • 运行两个嵌套循环,在以下条件下,从i的外部在[1,N]范围内,内部j[1,sum]范围内以自下而上的方式填充subset [] []矩阵:
      • 如果(j
      • 如果(j> = arr [i – 1]),则子集[i] [j] =子集[i – 1] [j] ||子集[i – 1] [j – arr [i – 1]]
    • 最后,返回子集[n] [sum]
  • 对哪个子集[N] [k]的第一个k是真实的,给出所要求的最大可能子序列和K 2。

下面是上述方法的实现:

C++
// C++ Program to implement
// the above approach
#include 
using namespace std;
bool isSubsetSum(int arr[], int n, int sum)
{
    bool subset[n + 1][sum + 1];
  
    // If sum is 0, then answer is true
    for (int i = 0; i <= n; i++)
        subset[i][0] = true;
  
    // If sum is not 0 and arr[] is empty,
    // then answer is false
    for (int i = 1; i <= sum; i++)
        subset[0][i] = false;
  
    // Fill the subset table in bottom up manner
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= sum; j++) {
  
            if (j < arr[i - 1])
                subset[i][j] = subset[i - 1][j];
  
            if (j >= arr[i - 1])
                subset[i][j]
                    = subset[i - 1][j]
                      || subset[i - 1][j - arr[i - 1]];
        }
    }
  
    return subset[n][sum];
}
// Function to find the sum
int findSum(int* arr, int n)
{
    int sum = 0;
    // Find sum of all values
    for (int i = 0; i < n; i++) {
        sum += arr[i];
    }
  
    int val = sqrt(sum);
  
    for (int i = val; i >= 0; i--) {
        if (isSubsetSum(arr, n, i * i)) {
            // return the value;
            return i * i;
        }
    }
  
    return 0;
}
  
// Driver Code
int main()
{
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int n = sizeof(arr) / sizeof(arr[0]);
    cout << findSum(arr, n) << endl;
    return 0;
}


Java
// Java program to implement 
// the above approach 
import java.util.*;
  
class GFG{
  
static boolean isSubsetSum(int arr[], 
                           int n, int sum)
{
    boolean[][] subset = new boolean[n + 1][sum + 1];
  
    // If sum is 0, then answer is true
    for(int i = 0; i <= n; i++)
        subset[i][0] = true;
  
    // If sum is not 0 and arr[] is empty,
    // then answer is false
    for(int i = 1; i <= sum; i++)
        subset[0][i] = false;
  
    // Fill the subset table in bottom up manner
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= sum; j++)
        {
            if (j < arr[i - 1])
                subset[i][j] = subset[i - 1][j];
  
            if (j >= arr[i - 1])
                subset[i][j] = subset[i - 1][j] ||
                subset[i - 1][j - arr[i - 1]];
        }
    }
    return subset[n][sum];
}
  
// Function to find the sum
static int findSum(int[] arr, int n)
{
    int sum = 0;
      
    // Find sum of all values
    for(int i = 0; i < n; i++)
    {
        sum += arr[i];
    }
  
    int val = (int)Math.sqrt(sum);
  
    for(int i = val; i >= 0; i--)
    {
        if (isSubsetSum(arr, n, i * i))
        {
              
            // return the value;
            return i * i;
        }
    }
    return 0;
}
  
// Driver code
public static void main(String[] args)
{
    int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int n = arr.length;
      
    System.out.println(findSum(arr, n));
}
}
  
// This code is contributed by offbeat


Python3
# Python3 program to implement
# the above approach
import math
  
def isSubsetSum(arr, n, sum):
      
    subset = [ [ True for x in range(sum + 1) ] 
                      for y in range(n + 1) ]
  
    # If sum is 0, then answer is true
    for i in range(n + 1):
        subset[i][0] = True
  
    # If sum is not 0 and arr[] is empty,
    # then answer is false
    for i in range(1, sum + 1):
        subset[0][i] = False
  
    # Fill the subset table in bottom up manner
    for i in range(1, n + 1):
        for j in range(1, sum + 1):
  
            if (j < arr[i - 1]):
                subset[i][j] = subset[i - 1][j]
  
            if (j >= arr[i - 1]):
                subset[i][j] = (subset[i - 1][j] or
                                subset[i - 1][j - 
                                   arr[i - 1]])
                                     
    return subset[n][sum]
  
# Function to find the sum
def findSum(arr, n):
      
    sum = 0
      
    # Find sum of all values
    for i in range(n):
        sum += arr[i]
  
    val = int(math.sqrt(sum))
  
    for i in range(val, -1, -1):
        if (isSubsetSum(arr, n, i * i)):
              
            # Return the value;
            return i * i
              
    return 0
  
# Driver Code
if __name__ == "__main__":
  
    arr = [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
    n = len(arr)
      
    print(findSum(arr, n))
  
# This code is contributed by chitranayal


C#
// C# program to implement 
// the above approach 
using System;
  
class GFG{
  
static bool isSubsetSum(int []arr, 
                        int n, int sum)
{
    bool[,] subset = new bool[n + 1, sum + 1];
  
    // If sum is 0, then answer is true
    for(int i = 0; i <= n; i++)
        subset[i, 0] = true;
  
    // If sum is not 0 and []arr is empty,
    // then answer is false
    for(int i = 1; i <= sum; i++)
        subset[0, i] = false;
  
    // Fill the subset table in bottom up manner
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= sum; j++)
        {
            if (j < arr[i - 1])
                subset[i, j] = subset[i - 1, j];
  
            if (j >= arr[i - 1])
                subset[i, j] = subset[i - 1, j] ||
                subset[i - 1, j - arr[i - 1]];
        }
    }
    return subset[n, sum];
}
  
// Function to find the sum
static int findSum(int[] arr, int n)
{
    int sum = 0;
      
    // Find sum of all values
    for(int i = 0; i < n; i++)
    {
        sum += arr[i];
    }
  
    int val = (int)Math.Sqrt(sum);
  
    for(int i = val; i >= 0; i--)
    {
        if (isSubsetSum(arr, n, i * i))
        {
              
            // return the value;
            return i * i;
        }
    }
    return 0;
}
  
// Driver code
public static void Main(String[] args)
{
    int []arr = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int n = arr.Length;
      
    Console.WriteLine(findSum(arr, n));
}
}
  
// This code is contributed by Rohit_ranjan


输出:
36

时间复杂度: O(N * SUM)
辅助空间: O(N * SUM)