📜  索引顺序在字典上最小,元素的总和为<= X

📅  最后修改于: 2021-05-06 08:51:11             🧑  作者: Mango

给定一个数组arr []和一个整数X ,任务是找到这样的索引:

  1. 找到的索引上的元素之和≤X
  2. 索引的数量是最大可能的。
  3. 索引的顺序在字典上最小,即{0,0,1}在字典上小于{1,0,0}

请注意,任何索引都可以选择一次以上。

例子:

方法:该问题看起来像是动态编程的一种变体,但事实证明,可以通过简单的贪婪算法来解决。

令具有第一最小值的索引为m。那么完成的最大索引数为n = X / A [m]。因此,ans = [m,m,m,…。,m],其中m的数量为n,是所选索引的最大数量的顺序,总和= nx A [m]。我们还确保最佳答案中包含n个值且不超过n个值。

现在,如果我们找到一个小于m的索引i,从而可以用值A [i的索引替换值A [m]的索引,则可以得到具有相同数量的选定索引的按字典顺序排列的较小顺序。 ]而不会超过总和X,那么我们可以将i中的第一个元素替换为i,从而使字典顺序上的顺序变小。为了使它在字典上尽可能小,我们希望索引i尽可能小,然后,我们希望使用它尽可能多的次数。

下面是上述方法的实现:

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


输出:
0 0 2 2

时间复杂度: O(NLog(N))