来自 [0, N] 的所有整数都显示为最小正缺失数 (MEX) 的最小操作
给定一个大小为N的数组arr[] ,任务是找到数组上的最小操作,使得在每个操作中,可以选择数组中的任何元素并将其递增1 ,这样对于范围内的所有i , MEX都是i [0, n] 。如果对于任何i如果MEX不是i打印-1 。
例子 :
Input : arr[] = {3, 0, 1, 0, 3}
Output:
MEX for i = 0 is 2
MEX for i = 1 is 1
MEX for i = 2 is 0
MEX for i = 3 is 4
MEX for i = 4 is 2
MEX for i = 5 is 3
Explanation:
For MEX = 0
In operation 1 choose index 1 and increment it by 1
In operation 2 choose index 3 and increment it by 1 the array becomes {3, 1, 1, 1, 3} MEX = 0. So 2 operations.
For MEX =1
In operation 1 choose index 2 and increment it by 1 the array becomes {3, 0, 2, 0, 3} MEX = 1. So 1 operation.
For MEX = 2, So 0 operation.
It is already having MEX = 2
For MEX = 3
In operation 1 choose index 0 and increment it by 1
In operation 2 choose index 3 and increment it by 1
In operation 3 choose index 1 and increment it by 1
In operation 3 choose index 1 and increment it by 1 , the array becomes {4, 2, 1, 0, 4} MEX = 3 so 4 operations.
Same for MEX = 4, 5 .
Input : {1, 2, 3, 4}
Output: 0 -1, -1, -1, -1
MEX for i = 0 is 0
MEX for i = 1 is -1
MEX for i = 2 is -1
MEX for i = 3 is -1
MEX for i = 4 is -1
方法:可以使用散列来解决这个问题来存储元素的频率,堆栈可以用来存储数组中的重复元素。 Hashmap 可用于存储MEX = i的频率,如果i已经存在于 hashmap 中,则增加所有出现的次数并将重复的元素存储在堆栈中,否则如果i的频率为0 ,则它已经是MEX ,所以0操作,现在在堆栈中查找重复出现并将其变为当前i以便对于i+1 , i不会变为MEX 。请按照以下步骤解决此问题:
- 初始化一个unordered_map freq[]来存储数组arr[]的频率和一个变量is_possible来跟踪MEX的可能性。
- 遍历数组arr[]并将频率存储在 hashmap freq 中。
- 初始化堆栈stk[]和向量 ops ,以存储MEX = i的最小操作, prev_cost以存储增加重复元素所需的成本。
- 如果is_possible == 0 ,则MEX = i是不可能的,所以存储-1 。
- 否则将freq[i]+ prev_cost存储在ops中。
- 如果freq[i]等于0检查堆栈中是否有某个元素将其弹出并将其递增到i并将prev_cost递增到ij并递增freq[i] ,如果堆栈为空则将 is_possible 设置为 false。
- 否则,如果freq[i]>1将重复推入堆栈stk[]并递减freq[i] 。
- 现在打印包含使MEX = i [0, n]的最小操作的向量ops 。
下面是上述方法的实现。
C++
// C++ program for the above approach
#include
using namespace std;
// Function to find the minimum operations
// to make the MEX = i
void find_min_operations(int arr[], int n)
{
// Initialize an unordered_map
// to store the frequencies
unordered_map freq;
// is_possible to store
// the possibility of MEX = i
bool is_possible = true;
// count the frequencies
// and store into the freq
for (int i = 0; i < n; i++) {
freq[arr[i]]++;
}
// Initialize stack to store
// the repeated elements
stack stk;
// ops store the minimum
// operations required for MEX =i
vector ops;
// prev_cost to store the
// cost to increment some
// repeated element to i-1
// if MEX initially is i-1 so
// that MEX remains i
int prev_cost = 0;
for (int i = 0; i <= n; i++) {
// Push -1 if it is not possible
if (is_possible == 0)
ops.push_back(-1);
else {
ops.push_back(freq[i] + prev_cost);
// If frequency of the element is 0
// then check for repeated element
// in the stack so that it can be added
// with i-j operations in next iteration
// and can be made it to i.
if (freq[i] == 0) {
// Check for repeated
// element in the stack
if (!stk.empty()) {
int j = stk.top();
stk.pop();
prev_cost += i - j;
// Increment the frequency of i since
// the repeated element j is made to i
freq[i]++;
}
// If no repeated element
// no possibility for MEX = i+1
// so make is_possible=false
else
is_possible = false;
}
// If i is already available
else {
// Push the repeated elements
// into the stack
while (freq[i] > 1) {
stk.push(i);
freq[i]--;
}
}
}
}
for (int i = 0; i < ops.size(); i++) {
cout << "MEX for i = "
<< i << " is " << ops[i]
<< endl;
}
}
// Driver Code
int main()
{
// Initializing array arr[]
int arr[] = { 3, 0, 1, 0, 3 };
int n = sizeof(arr) / sizeof(arr[0]);
// Function call
find_min_operations(arr, n);
return 0;
}
Python3
# Python3 program for the above approach
from collections import deque
# Function to find the minimum operations
# to make the MEX = i
def find_min_operations(arr, n):
# Initialize an unordered_map
# to store the frequencies
freq = {}
# is_possible to store
# the possibility of MEX = i
is_possible = True
# Count the frequencies
# and store into the freq
for i in range(0, n):
if arr[i] in freq:
freq[arr[i]] += 1
else:
freq[arr[i]] = 1
# Initialize stack to store
# the repeated elements
stk = deque()
# ops store the minimum
# operations required for MEX =i
ops = []
# prev_cost to store the
# cost to increment some
# repeated element to i-1
# if MEX initially is i-1 so
# that MEX remains i
prev_cost = 0
for i in range(0, n + 1):
# Push -1 if it is not possible
if (is_possible == 0):
ops.append(-1)
else:
if i in freq:
ops.append(freq[i] + prev_cost)
else:
ops.append(prev_cost)
# If frequency of the element is 0
# then check for repeated element
# in the stack so that it can be added
# with i-j operations in next iteration
# and can be made it to i.
if (not (i in freq)):
# Check for repeated
# element in the stack
if (len(stk) != 0):
j = stk.popleft()
prev_cost += i - j
# Increment the frequency of i since
# the repeated element j is made to i
freq[i] = freq[i] + 1 if i in freq else 1
# If no repeated element
# no possibility for MEX = i+1
# so make is_possible=false
else:
is_possible = False
# If i is already available
else:
# Push the repeated elements
# into the stack
while (freq[i] > 1):
stk.append(i)
freq[i] -= 1
for i in range(0, len(ops)):
print(f"MEX for i = {i} is {ops[i]}")
# Driver Code
if __name__ == "__main__":
# Initializing array arr[]
arr = [ 3, 0, 1, 0, 3 ]
n = len(arr)
# Function call
find_min_operations(arr, n)
# This code is contributed by rakeshsahni
MEX for i = 0 is 2
MEX for i = 1 is 1
MEX for i = 2 is 0
MEX for i = 3 is 4
MEX for i = 4 is 2
MEX for i = 5 is 3
时间复杂度: O(N) 其中 N 是数组的大小
辅助空间: O(N)