给定一个大小为K的正整数的排序数组arr[]和一个整数N ,其中一些数字可以插入到数组中,这样所有正整数[1, N]都可以作为修改后的数组的子集之和获得.任务是找到所需的最少插入次数。
注意:数组的最小长度可以是 1。
例子:
Input: K = 2, arr = [1, 2], N = 4
Output: 1
Explanation We need to insert either 3 or 4 in the array.
Input: K = 4, arr = [1, 2, 4, 8], N = 15
Output: 0
方法:这个问题可以使用贪心方法来解决。
- 通过包含给定数组 arr[] 中的一些元素和/或添加所需的其他缺失元素,形成一个列表,说X[]形成一个总和到 N 所需的基本元素。
- 最初,从空列表 X[] 开始,使用来自 X[] 的数字的可能和的范围是 [0, 0]。
- 假设范围[1, m] (m < N) 中的元素可以表示为该时刻列表X[]中存在的元素的总和,并且添加了直到 arr[] 的索引 i 的数字.
以下是以下可能性:
- If the (i+1)th number of arr[] is = (m + 1), then the extra sums possible are:
(m + 1), (m + 2), (m + 3)…, (m + m + 1).
Hence, the range becomes [1, ((2 * m) + 1)]. Add the number arr[i+1] to X[]. Increment the value of i. - If the (i+1)th number of arr[] is < (m + 1), let it be k, then extra sums possible are:
(1 + k), (2 + k), (3 + k), …(m + k).
Hence, the range becomes [1, (m + k)]. Add the number arr[i+1] to X[] Increment the value of i. - If the (i+1)th number of arr[] is > (m + 1), then (m + 1) should be inserted to the array X[], else there is no way to obtain a sum of (m + 1) by these numbers.
Hence, the range becomes [1, ((2 * m) + 1)] after insertion of (m + 1). Do not increment the value of i.
- 重复这个过程,直到范围跨越给定的数字 N。
- 即使这样做之后,如果数组 arr[] 中的所有数字都被遍历,并且范围还没有越过 N,那么就需要继续向 X[] 添加越来越多的数字,直到范围越过 N。
- X[]和arr[]的大小之间的差异是所需的最少插入次数。
- 在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 现场工作专业课程和学生竞争性编程现场课程。