📌  相关文章
📜  最小化数组中的插入以获得最大为 N 的所有和

📅  最后修改于: 2021-10-26 05:45:44             🧑  作者: Mango

给定一个大小为K的正整数的排序数组arr[]和一个整数N ,其中一些数字可以插入到数组中,这样所有正整数[1, N]都可以作为修改后的数组的子集之和获得.任务是找到所需的最少插入次数。
注意:数组的最小长度可以是 1。
例子:

方法:这个问题可以使用贪心方法来解决。

  1. 通过包含给定数组 arr[] 中的一些元素和/或添加所需的其他缺失元素,形成一个列表,说X[]形成一个总和到 N 所需的基本元素。
  2. 最初,从空列表 X[] 开始,使用来自 X[] 的数字的可能和的范围是 [0, 0]。
  3. 假设范围[1, m] (m < N) 中的元素可以表示为该时刻列表X[]中存在的元素的总和,并且添加了直到 arr[] 的索引 i 的数字.
    以下是以下可能性:
  1. 重复这个过程,直到范围跨越给定的数字 N。
  2. 即使这样做之后,如果数组 arr[] 中的所有数字都被遍历,并且范围还没有越过 N,那么就需要继续向 X[] 添加越来越多的数字,直到范围越过 N。
  3. X[]arr[]的大小之间的差异是所需的最少插入次数
  4. X[] 中包含所有基本元素后,范围应至少为[1, N] ,并且从给定列表外部插入的次数最少。

注意:不是维护列表 X[],计数器变量ans可以初始化为 0,每次添加新元素时,计数器值都可以递增。计数器变量的值是所需的答案。
下面是上述方法的实现:

C++
// C++ code to minimize insertions
// such that sum of subsets of
// array elements form all numbers
// up to N
#include 
using namespace std;
 
#define N 100005
 
int minInsertions(vector& v, int n)
{
 
    // initialised rangeEnd which
    // denotes the range covered,
    // [1, rangeEnd] ans denotes
    // the number of insertions made
    // so far
    int rangeEnd = 0, ans = 0;
    for (auto i : v) {
 
        // in the case where our next
        // number is greater than
        // rangeEnd+1, it is compulsory
        // to insert rangeEnd+1
        while (i > rangeEnd + 1) {
 
            ans++;
            rangeEnd = rangeEnd * 2 + 1;
            if (rangeEnd >= n) {
                return ans;
            }
        }
 
        // otherwise we just move
        // forward our rangeEnd
        rangeEnd += i;
        if (rangeEnd >= n) {
            return ans;
        }
    }
 
    // after we have included all
    // elements in the array and have
    // still not reached n, we insert
    // numbers = rangeEnd+1 till
    // we reach n
    while (rangeEnd < n) {
        ans++;
        rangeEnd = rangeEnd * 2 + 1;
    }
    return ans;
}
 
// Driver Program
signed main()
{
    // the size of the given array
    int k = 4;
 
    // the given number n
    int n = 15;
    std::vector v = { 1, 6, 7, 9 };
    cout << minInsertions(v, n);
 
    return 0;
}


Java
// Java code to minimize insertions
// such that sum of subsets of
// array elements form all numbers
// up to N
class GFG
{
      int N = 100005;
     
    static int minInsertions(int []v, int n)
    {
     
        // initialised rangeEnd which
        // denotes the range covered,
        // [1, rangeEnd] ans denotes
        // the number of insertions made
        // so far
        int rangeEnd = 0, ans = 0;
        for (int i : v)
        {
     
            // in the case where our next
            // number is greater than
            // rangeEnd+1, it is compulsory
            // to insert rangeEnd+1
            while (i > rangeEnd + 1)
            {
                ans++;
                rangeEnd = rangeEnd * 2 + 1;
                if (rangeEnd >= n)
                {
                    return ans;
                }
            }
     
            // otherwise we just move
            // forward our rangeEnd
            rangeEnd += i;
            if (rangeEnd >= n)
            {
                return ans;
            }
        }
     
        // after we have included all
        // elements in the array and have
        // still not reached n, we insert
        // numbers = rangeEnd+1 till
        // we reach n
        while (rangeEnd < n)
        {
            ans++;
            rangeEnd = rangeEnd * 2 + 1;
        }
        return ans;
    }
     
    // Driver Program
    public static void main (String[] args)
    {
        // the size of the given array
        int k = 4;
     
        // the given number n
        int n = 15;
        int v[] = { 1, 6, 7, 9 };
        System.out.println(minInsertions(v, n));
    }
}
 
// This code is contributed by AnkitRai01


Python3
# Python3 program to minimize insertions
# such that sum of subsets of
# array elements form all numbers
# up to N
N = 100005
   
def minInsertions(v, n):
  
    # Initialised rangeEnd which
    # denotes the range covered,
    # [1, rangeEnd] ans denotes
    # the number of insertions made
    # so far
    rangeEnd, ans = 0, 0
    for i in v:
   
        # In the case where our next
        # number is greater than
        # rangeEnd+1, it is compulsory
        # to insert rangeEnd+1
        while (i > rangeEnd + 1):
            ans += 1
            rangeEnd = rangeEnd * 2 + 1
            if (rangeEnd >= n):
                return ans
   
        # Otherwise we just move
        # forward our rangeEnd
        rangeEnd += i
        if (rangeEnd >= n):
            return ans
   
    # After we have included all
    # elements in the array and have
    # still not reached n, we insert
    # numbers = rangeEnd+1 till
    # we reach n
    while (rangeEnd < n):
        ans += 1
        rangeEnd = rangeEnd * 2 + 1
    return ans
   
# Driver code
if __name__ == "__main__":
      
    # The size of the given array
    k = 4
   
    # The given number n
    n = 15
    v = [ 1, 6, 7, 9 ]
 
    print(minInsertions(v, n))
 
# This code is contributed by chitranayal


C#
// C# program to minimize insertions
// such that sum of subsets of
// array elements form all numbers
// up to N
using System;
 
class GFG{
 
//int N = 100005;
     
static int minInsertions(int []v, int n)
{
     
    // Initialised rangeEnd which
    // denotes the range covered,
    // [1, rangeEnd] ans denotes
    // the number of insertions made
    // so far
    int rangeEnd = 0, ans = 0;
     
    foreach(int i in v)
    {
         
        // In the case where our next
        // number is greater than
        // rangeEnd+1, it is compulsory
        // to insert rangeEnd+1
        while (i > rangeEnd + 1)
        {
            ans++;
            rangeEnd = rangeEnd * 2 + 1;
            if (rangeEnd >= n)
            {
                return ans;
            }
        }
     
        // Otherwise we just move
        // forward our rangeEnd
        rangeEnd += i;
        if (rangeEnd >= n)
        {
            return ans;
        }
    }
     
    // After we have included all
    // elements in the array and have
    // still not reached n, we insert
    // numbers = rangeEnd+1 till
    // we reach n
    while (rangeEnd < n)
    {
        ans++;
        rangeEnd = rangeEnd * 2 + 1;
    }
    return ans;
}
     
// Driver code
public static void Main(String[] args)
{
     
    // The size of the given array
    //int k = 4;
     
    // The given number n
    int n = 15;
    int []v = { 1, 6, 7, 9 };
     
    Console.WriteLine(minInsertions(v, n));
}
}
 
// This code is contributed by Rajput-Ji


Javascript


输出:
2

时间复杂度: O(K + log(N))

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程