给定一个数组arr[] ,任务是找到形成完美平方的子序列的总和。如果有多个子序列的总和等于一个完全平方数,则打印最大和。
解释:
Input: arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}
Output: 36
Explanation:
Maximum possible sum which is a perfect square that can be obtained from the array is 36 obtained from the subsequence {1, 5, 6, 7, 8, 9}.
Input: arr[] = {9, 10}
Output: 9
朴素方法:生成给定数组的所有可能子序列,对于每个子序列,检查其总和是否为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 < arr[i – 1]),则子集[i][j] = 子集[i – 1][j]
- 如果 (j >= arr[i – 1]),那么子集[i][j] = 子集[i – 1][j] ||子集[i – 1][j – arr[i – 1]]
- 最后,返回subset[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
Javascript
输出:
36
时间复杂度: O(N * SUM)
辅助空间: O(N * SUM)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。