对于每个 A[i] 找到所有元素小于 A[i] 总和大于 B[i] 的最小子集
给定两个包含N个整数的数组A[]和B[] ,任务是为每个元素 A[i] 找到索引的最小子集S的大小,这样:
- 与子集S中的索引对应的每个值都严格小于A[i] 。
- 与 B 中的索引对应的元素之和严格大于B[i] 。
例子:
Input: N = 5, A = {3, 2, 100, 4, 5}, B = {1, 2, 3, 4, 5}
Output: {1, -1, 1, -1, 3}
Explanation: Subsets for each element of A are :
A[0] : {1}, (A[1] < A[0] and B[1] > B[0])
A[1] : {}, (no such subset exist )
A[2] : {4}, (A[4] < A[2] and B[4] > B[2])
A[3] : {}, (no such subset exist )
A[4] : {0, 1, 3}, (A[0] < A[4], A[1] < A[4], A[3] < A[4] and (B[0]+B[1]+B[3] > B[4]) )
Input : N = 4, A = {1, 1, 1, 1}, B = {2, 4, 5, 9}
Output : {-1, -1, -1, -1}
方法:该问题可以通过使用多重集的贪心方法来解决,具体思路如下:
Sort the array A[] along with their indices and for each element in sorted array find the smallest subset having elements of B with sum greater than current element of B.
Use multiset in decreasing order to store elements of B.
请按照以下步骤解决此问题:
- 声明一个成对的向量v ,它存储数组 A 的元素及其索引。
- 对向量v进行排序。排序后,每个元素都满足第一个条件。
- 声明一个 multiset s ,以便 multiset 中的元素按降序排列。
- 遍历向量v并在每次迭代时:
- 将数组 B 中与向量的第 i 个元素(即对的第二个元素)中的索引相对应的元素存储在变量curr_B 中。
- 遍历集合,同时保持集合元素的计数和总和,直到总和刚好大于curr_B 。
- 将 curr_B 插入集合,并将为第 i 个元素找到的(所需集合的)计数到存储答案( ans)的数组中。
- 完成所有迭代后返回ans向量。
以下是上述方法的实现:
C++
// C++ program for Find minimum size of subset
// for each index of the array satisfying the
// given condition
#include
using namespace std;
// Functions to print minimum size of subset
// for each element satisfying the given conditions
void printSubsets(int N, int A[], int B[])
{
// storing the elements of A along with
// their indices in a vector of pairs v
vector > v(N);
for (int i = 0; i < N; i++) {
v[i] = { A[i], i };
}
// sorting the vector v
sort(v.begin(), v.end());
// declaring a vector of size N to
// store the answer
vector ans(N);
// declaring a multiset to store the
// corresponding values of B
multiset > s;
// iterating through the sorted vector v.
// Since the vector is sorted, so the 1st
// condition is already fulfilled, i.e.
// all the elements of A at indices of resultant
// set would be less than current A[i]
for (int i = 0; i < N; i++) {
int curr_B = B[v[i].second];
int size = 0;
int sum = 0;
// iterating through the set to find
// the minimum set whose sum>B[i]
//(or curr_B)
for (auto x : s) {
sum += x;
size += 1;
if (sum > curr_B)
break;
}
// inserting the current element of B
// into the set
s.insert(curr_B);
// if sum>B[i] condition is fulfilled,
// we assign size of resultant subset to
// the answer at the index
if (sum > curr_B) {
ans[v[i].second] = size;
}
// else we assign -1
else {
ans[v[i].second] = -1;
}
}
// printing the answer
for (int i = 0; i < N; i++) {
cout << ans[i] << " ";
}
}
// Driver Code
int main()
{
int N = 5;
int A[] = { 3, 2, 100, 4, 5 };
int B[] = { 1, 2, 4, 3, 5 };
printSubsets(N, A, B);
}
Python3
# Python program to find the minimum size of the subset
# for each index of the array satisfying the given condition
import bisect
#Functions to print minimum size of subset
#for each element satisfying the given conditions
def printSubsets(N, A, B):
#storing the elements of A along with
#their indices in a vector of pairs v
v = [[A[i], i] for i in range(N)]
v.sort() #sorting v
#initializing ans, s
ans = [0] * N
s = list()
for i in range(N):
curr_B = B[v[i][1]]
size = 0
sums = 0
for ele in s:
sums += ele
size += 1
if sums > curr_B:
break
#to ensure that sorted status of s is maintained
bisect.insort(s, curr_B)
if (sums > curr_B):
ans[v[i][1]] = size
else:
ans[v[i][1]] = -1
print(" ".join(list(map(str, ans))))
# Driver Code
N = 5
A = [3, 2, 100, 4, 5]
B = [1, 2, 4, 3, 5]
printSubsets(N, A, B)
# This code is contributed by phalasi.
1 -1 1 -1 3
时间复杂度: O(N^2)
辅助空间: O(N)