给定一个由N个整数和一个整数K组成的数组arr [] ,任务是找到两个最小唯一子集的长度之和,其元素之和至少为K。
例子:
Input: arr[] = {2, 4, 5, 6, 7, 8}, K = 16
Output: 6
Explanation:
The subsets {2, 6, 8} and {4, 5, 7} are the two smallest subsets with sum K(= 16).
Therefore, the sum of the lengths of both these subsets = 3 + 3 = 6.
Input: arr[] = {14, 3, 7, 8, 9, 7, 12, 15, 10, 6}, K = 40
Output: 8
方法:可以根据以下观察结果解决给定问题:
- 对数组进行排序可以解决以下问题:选择在索引[i,N]的范围内总和至少为K的子数组,然后检查索引[i,N]范围内的其余数组元素的总和是否为是否为K。
- 为了实现上述想法,使用二维数组dp [] [] ,使得dp [i] [j]存储索引值至少为[i,N]的子集的最小和。 j。那么过渡状态类似于0/1背包,可以定义为:
- 如果arr [i]的值大于j ,则将dp [i] [j]更新为arr [i] 。
- 否则,将dp [i] [j]更新为dp [i +1] [j]和(dp [i +1] [j – arr [i]] + arr [i])的最小值。
请按照以下步骤解决问题:
- 以升序对数组进行排序。
- 初始化一个数组,例如suffix [],并在其中存储数组arr []的后缀和。
- 初始化一个二维数组,例如dp [] [],以使dp [i] [j]存储索引值至少为j的索引[i,N]范围内子集的最小和。
- 将dp [N] [0]初始化为0,并将所有其他状态初始化为INT_MAX 。
- 以相反的顺序遍历数组arr [i]并执行以下步骤:
- 以相反的顺序遍历索引[0,K]的范围,并执行以下操作:
- 如果arr [i]的值至少为j ,则将dp [i] [j]的值更新为arr [i],因为当前状态的总和至少为j 。现在,继续迭代。
- 如果下一个状态的值,即dp [i +1] [j – arr [i]]为INT_MAX ,则将dp [i] [j]更新为INT_MAX 。
- 否则,将dp [i] [j]更新为dp [i + 1] [j]和(dp [i +1] [j – arr [i]] + arr [i])的最小值,以存储所有值的总和至少为j 。
- 以相反的顺序遍历索引[0,K]的范围,并执行以下操作:
- 现在,以相反的顺序遍历数组suffix [] ,如果(suffix [i] – dp [i] [K])的值至少为K ,则打印(N – i)作为形成了两个最小的子集并打破了循环。
- 否则,打印“ -1” 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
const int MAX = 1e9;
// Function to calculate sum of lengths
// of two smallest subsets with sum >= K
int MinimumLength(int A[], int N, int K)
{
// Sort the array in ascending order
sort(A, A + N);
// Stores suffix sum of the array
int suffix[N + 1] = { 0 };
// Update the suffix sum array
for (int i = N - 1; i >= 0; i--)
suffix[i] = suffix[i + 1] + A[i];
// Stores all dp-states
int dp[N + 1][K + 1];
// Intialize all dp-states
// with a maximum possible value
for (int i = 0; i <= N; i++)
for (int j = 0; j <= K; j++)
dp[i][j] = MAX;
// Base Case
dp[N][0] = 0;
// Traverse the array arr[]
for (int i = N - 1; i >= 0; i--) {
// Iterate over the range [0, K]
for (int j = K; j >= 0; j--) {
// If A[i] is equal to at
// least the required sum
// j for the current state
if (j <= A[i]) {
dp[i][j] = A[i];
continue;
}
// If the next possible
// state doesn't exist
if (dp[i + 1][j - A[i]] == MAX)
dp[i][j] = MAX;
// Otherwise, update the current
// state to the minimum of the
// next state and state including
// the current element A[i]
else
dp[i][j] = min(dp[i + 1][j],
dp[i + 1][j - A[i]] + A[i]);
}
}
// Traverse the suffix sum array
for (int i = N - 1; i >= 0; i--) {
// If suffix[i] - dp[i][K] >= K
if (suffix[i] - dp[i][K] >= K) {
// Sum of lengths of the two
// smallest subsets is obtained
return N - i;
}
}
// Return -1, if there doesn't
// exist any subset of sum >= K
return -1;
}
// Driver Code
int main()
{
int arr[] = { 7, 4, 5, 6, 8 };
int K = 13;
int N = sizeof(arr) / sizeof(arr[0]);
cout << MinimumLength(arr, N, K);
return 0;
}
Java
// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
class GFG{
static int MAX = (int)(1e9);
// Function to calculate sum of lengths
// of two smallest subsets with sum >= K
static int MinimumLength(int A[], int N, int K)
{
// Sort the array in ascending order
Arrays.sort(A);
// Stores suffix sum of the array
int suffix[] = new int[N + 1];
// Update the suffix sum array
for(int i = N - 1; i >= 0; i--)
suffix[i] = suffix[i + 1] + A[i];
// Stores all dp-states
int dp[][] = new int[N + 1][K + 1];
// Intialize all dp-states
// with a maximum possible value
for(int i = 0; i <= N; i++)
for(int j = 0; j <= K; j++)
dp[i][j] = MAX;
// Base Case
dp[N][0] = 0;
// Traverse the array arr[]
for(int i = N - 1; i >= 0; i--)
{
// Iterate over the range [0, K]
for(int j = K; j >= 0; j--)
{
// If A[i] is equal to at
// least the required sum
// j for the current state
if (j <= A[i])
{
dp[i][j] = A[i];
continue;
}
// If the next possible
// state doesn't exist
if (dp[i + 1][j - A[i]] == MAX)
dp[i][j] = MAX;
// Otherwise, update the current
// state to the minimum of the
// next state and state including
// the current element A[i]
else
dp[i][j] = Math.min(dp[i + 1][j],
dp[i + 1][j - A[i]]
+ A[i]);
}
}
// Traverse the suffix sum array
for(int i = N - 1; i >= 0; i--)
{
// If suffix[i] - dp[i][K] >= K
if (suffix[i] - dp[i][K] >= K)
{
// Sum of lengths of the two
// smallest subsets is obtained
return N - i;
}
}
// Return -1, if there doesn't
// exist any subset of sum >= K
return -1;
}
// Driver Code
public static void main(String[] args)
{
int arr[] = { 7, 4, 5, 6, 8 };
int K = 13;
int N = arr.length;
System.out.println(MinimumLength(arr, N, K));
}
}
// This code is contributed by Kingash
Python3
# Python3 program for the above approach
MAX = 1e9
# Function to calculate sum of lengths
# of two smallest subsets with sum >= K
def MinimumLength(A, N, K):
# Sort the array in ascending order
A.sort()
# Stores suffix sum of the array
suffix = [0] * (N + 1)
# Update the suffix sum array
for i in range(N - 1, -1, -1):
suffix[i] = suffix[i + 1] + A[i]
# Stores all dp-states
dp = [[0] * (K + 1)] * (N + 1)
# Intialize all dp-states
# with a maximum possible value
for i in range(N + 1):
for j in range(K + 1):
dp[i][j] = MAX
# Base Case
dp[N][0] = 0
# Traverse the array arr[]
for i in range(N - 1, -1, -1):
# Iterate over the range [0, K]
for j in range(K, -1, -1):
# If A[i] is equal to at
# least the required sum
# j for the current state
if (j <= A[i]) :
dp[i][j] = A[i]
continue
# If the next possible
# state doesn't exist
if (dp[i + 1][j - A[i]] == MAX):
dp[i][j] = MAX
# Otherwise, update the current
# state to the minimum of the
# next state and state including
# the current element A[i]
else :
dp[i][j] = min(dp[i + 1][j],
dp[i + 1][j - A[i]] + A[i])
# Traverse the suffix sum array
for i in range(N - 1, -1, -1):
# If suffix[i] - dp[i][K] >= K
if (suffix[i] - dp[i][K] >= K):
# Sum of lengths of the two
# smallest subsets is obtained
return N - i
# Return -1, if there doesn't
# exist any subset of sum >= K
return -1
# Driver Code
arr = [ 7, 4, 5, 6, 8 ]
K = 13
N = len(arr)
print(MinimumLength(arr, N, K))
# This code is contributed by splevel62
C#
// C# program for the above approach
using System;
class GFG{
static int MAX = (int)(1e9);
// Function to calculate sum of lengths
// of two smallest subsets with sum >= K
static int MinimumLength(int[] A, int N, int K)
{
// Sort the array in ascending order
Array.Sort(A);
// Stores suffix sum of the array
int[] suffix = new int[N + 1];
// Update the suffix sum array
for(int i = N - 1; i >= 0; i--)
suffix[i] = suffix[i + 1] + A[i];
// Stores all dp-states
int[,] dp = new int[N + 1, K + 1];
// Intialize all dp-states
// with a maximum possible value
for(int i = 0; i <= N; i++)
for(int j = 0; j <= K; j++)
dp[i, j] = MAX;
// Base Case
dp[N, 0] = 0;
// Traverse the array arr[]
for(int i = N - 1; i >= 0; i--)
{
// Iterate over the range [0, K]
for(int j = K; j >= 0; j--)
{
// If A[i] is equal to at
// least the required sum
// j for the current state
if (j <= A[i])
{
dp[i, j] = A[i];
continue;
}
// If the next possible
// state doesn't exist
if (dp[i + 1, j - A[i]] == MAX)
dp[i, j] = MAX;
// Otherwise, update the current
// state to the minimum of the
// next state and state including
// the current element A[i]
else
dp[i, j] = Math.Min(dp[i + 1, j],
dp[i + 1, j - A[i]]
+ A[i]);
}
}
// Traverse the suffix sum array
for(int i = N - 1; i >= 0; i--)
{
// If suffix[i] - dp[i][K] >= K
if (suffix[i] - dp[i, K] >= K)
{
// Sum of lengths of the two
// smallest subsets is obtained
return N - i;
}
}
// Return -1, if there doesn't
// exist any subset of sum >= K
return -1;
}
// Driver Code
public static void Main(string[] args)
{
int[] arr = { 7, 4, 5, 6, 8 };
int K = 13;
int N = arr.Length;
Console.WriteLine(MinimumLength(arr, N, K));
}
}
// This code is contributed by ukasp
输出:
4
时间复杂度: O(N * K)
辅助空间: O(N * K)