给定一个由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 Knapsack 可以定义为:
- 如果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]存储在索引[i, N]范围内具有至少 j值的子集的最小总和。
- 将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];
// Initialize 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];
// Initialize 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)
# Initialize 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];
// Initialize 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
Javascript
输出:
4
时间复杂度: O(N * K)
辅助空间: O(N * K)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live