给定一个数组arr[]和一个整数X ,任务是找到这样的索引:
- 找到的索引上的元素总和≤ X
- 索引的数量是最大可能的。
- 索引的顺序是字典序最小的,即 {0, 0, 1} 在字典序上小于 {1, 0, 0}
请注意,可以多次选择任何索引。
例子:
Input: arr[] = {6, 8, 5, 4, 7}, X = 11
Output: 0 2
Optimal answer is [0, 2] as it is lexicographically smallest.
sum of chosen indices A[0] + A[2] = 6 + 5 = 11 which is ≤ 11.
Here, [2, 3], [2, 2] or [3, 3] also give the maximum
number of chosen indices but they are not lexicographically smallest.
Input: arr[] = {9, 6, 8, 5, 7, 4}, X = 35
Output: 1 3 5 5 5 5 5 5
方法:这个问题看起来像是动态规划的变体,但事实证明它可以通过简单的贪心算法解决。
设具有第一个最小值的索引为 m。那么完成的最大索引数是 n = X / A[m]。所以 ans = [m, m, m, …., m],其中 m 的数量是 n,是所选索引的最大数量的顺序,总和 = nx A[m]。我们也确信最优答案有 n 个值,并且不超过这个值。
现在,如果我们可以找到一个小于 m 的索引 i,我们可以用相同数量的所选索引获得字典序较小的顺序,这样我们就可以用值 A[i] 的索引替换值 A[m] 的索引] 在不超过总和 X 的情况下,我们可以用 i 替换 ans 中的第一个元素,使顺序在字典上更小。为了使它在字典上尽可能小,我们希望索引 i 尽可能小,然后我们希望尽可能多地使用它。
For example, X = 11, A = [6, 8, 5, 4, 7].
The minimum value is at index 3 and A[3] = 4. So n = 11 / 4 = 2 and ans = [3, 3] with total sum = 4 x 2 = 8.
To make it lexicographically smaller, we will check the indices before 3 in order.
The first one is 6. Since 8 – 4 + 6 = 10 < 11. We have found out a smaller order [0, 3].
If we apply 6 again, we would get 10 – 4 + 6 = 12 > 11. So we go ahead to check the next index value 8, which is too large. So we go ahead to check 5. Since 10 – 4 + 5 = 11 <= 11, we find a smaller order [0, 2]. Since there is no room left for replacement, 11 – 11 = 0, we stop here. The final answer is [0, 2].
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to return the chosen indices
vector solve(int X, vector& A)
{
int min = INT_MAX;
int ind = -1;
for (int i = 0; i < A.size(); i++) {
if (A[i] < min) {
min = A[i];
ind = i;
}
}
// Maximum indices chosen
int maxIndChosen = X / min;
vector ans;
if (maxIndChosen == 0) {
return ans;
}
for (int i = 0; i < maxIndChosen; i++) {
ans.push_back(ind);
}
int temp = maxIndChosen;
int sum = maxIndChosen * A[ind];
// Try to replace the first element in ans by i,
// making the order lexicographically smaller
for (int i = 0; i < ind; i++) {
// If no further replacement possible return
if (sum - X == 0 || temp == 0)
break;
// If found an index smaller than ind and sum
// not exceeding X then remove index of smallest
// value from ans and then add index i to ans
while ((sum - A[ind] + A[i]) <= X && temp != 0) {
ans.erase(ans.begin());
ans.push_back(i);
temp--;
sum += (A[i] - A[ind]);
}
}
sort(ans.begin(), ans.end());
return ans;
}
// Driver code
int main()
{
vector A = { 5, 6, 4, 8 };
int X = 18;
vector ans = solve(X, A);
// Print the chosen indices
for (int i = 0; i < ans.size(); i++)
cout << ans[i] << " ";
return 0;
}
Java
// Java implementation of the approach
import java.util.*;
class GFG
{
// Function to return the chosen indices
static Vector solve(int X, Vector A)
{
int min = Integer.MAX_VALUE;
int ind = -1;
for (int i = 0; i < A.size(); i++)
{
if (A.get(i) < min)
{
min = A.get(i);
ind = i;
}
}
// Maximum indices chosen
int maxIndChosen = X / min;
Vector ans = new Vector<>();
if (maxIndChosen == 0)
{
return ans;
}
for (int i = 0; i < maxIndChosen; i++)
{
ans.add(ind);
}
int temp = maxIndChosen;
int sum = maxIndChosen * A.get(ind);
// Try to replace the first element in ans by i,
// making the order lexicographically smaller
for (int i = 0; i < ind; i++) {
// If no further replacement possible return
if (sum - X == 0 || temp == 0)
break;
// If found an index smaller than ind and sum
// not exceeding X then remove index of smallest
// value from ans and then add index i to ans
while ((sum - A.get(ind) + A.get(i)) <= X && temp != 0)
{
ans.remove(0);
ans.add(i);
temp--;
sum += (A.get(i) - A.get(ind));
}
}
Collections.sort(ans);
return ans;
}
// Driver code
public static void main(String args[])
{
Integer arr[] = { 5, 6, 4, 8 };
Vector A = new Vector(Arrays.asList(arr));
int X = 18;
Vector ans = solve(X, A);
// Print the chosen indices
for (int i = 0; i < ans.size(); i++)
System.out.print(ans.get(i)+" ");
}
}
/* This code contributed by PrinciRaj1992 */
Python3
# Python3 implementation of the approach
import sys;
# Function to return the chosen indices
def solve(X, A) :
minimum = sys.maxsize;
ind = -1;
for i in range(len(A)) :
if (A[i] < minimum ) :
minimum = A[i];
ind = i;
# Maximum indices chosen
maxIndChosen = X // minimum ;
ans = [];
if (maxIndChosen == 0) :
return ans;
for i in range(maxIndChosen) :
ans.append(ind);
temp = maxIndChosen;
sum = maxIndChosen * A[ind];
# Try to replace the first element in ans by i,
# making the order lexicographically smaller
for i in range(ind) :
# If no further replacement possible return
if (sum - X == 0 or temp == 0) :
break;
# If found an index smaller than ind and sum
# not exceeding X then remove index of smallest
# value from ans and then add index i to ans
while ((sum - A[ind] + A[i]) <= X and temp != 0) :
del(ans[0]);
ans.append(i);
temp -= 1;
sum += (A[i] - A[ind]);
ans.sort();
return ans;
# Driver code
if __name__ == "__main__" :
A = [ 5, 6, 4, 8 ];
X = 18;
ans = solve(X, A);
# Print the chosen indices
for i in range(len(ans)) :
print(ans[i],end= " ");
# This code is contributed by AnkitRai01
C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
class GFG
{
// Function to return the chosen indices
static List solve(int X, List A)
{
int min = int.MaxValue;
int ind = -1;
for (int i = 0; i < A.Count; i++)
{
if (A[i] < min)
{
min = A[i];
ind = i;
}
}
// Maximum indices chosen
int maxIndChosen = X / min;
List ans = new List();
if (maxIndChosen == 0)
{
return ans;
}
for (int i = 0; i < maxIndChosen; i++)
{
ans.Add(ind);
}
int temp = maxIndChosen;
int sum = maxIndChosen * A[ind];
// Try to replace the first element in ans by i,
// making the order lexicographically smaller
for (int i = 0; i < ind; i++)
{
// If no further replacement possible return
if (sum - X == 0 || temp == 0)
break;
// If found an index smaller than ind and sum
// not exceeding X then remove index of smallest
// value from ans and then add index i to ans
while ((sum - A[ind] + A[i]) <= X && temp != 0)
{
ans.RemoveAt(0);
ans.Add(i);
temp--;
sum += (A[i] - A[ind]);
}
}
ans.Sort();
return ans;
}
// Driver code
public static void Main(String []args)
{
int []arr = { 5, 6, 4, 8 };
List A = new List(arr);
int X = 18;
List ans = solve(X, A);
// Print the chosen indices
for (int i = 0; i < ans.Count; i++)
Console.Write(ans[i] + " ");
}
}
// This code is contributed by 29AjayKumar
Javascript
0 0 2 2
时间复杂度: O(NLog(N))
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。