Дан массив из N целых чисел. Пройдитесь по всему массиву и выберите K позиций, содержащих одинаковые значения. Эти выбранные K затем удаляются из массива. Если мы не можем выбрать значения K, то никакие места не могут быть удалены из массива.
Задача состоит в том, чтобы минимизировать количество различных целых чисел в массиве, доступном после каждой итерации.
Для данного Q запросов, с каждым запросом с номером P. Для каждого запроса выведите количество различных целых чисел в массиве после выполнения P итераций.
1<= N <= 10^6
1<= K <= 10
1<= Q <= 10^5
0<= C <= 10^5
1 <= P <= N
Example:
N=5
K=1
Q=3
Array = [5,0,1,2,1];
Queries (Various P values):
1
5
3
Output:
3
0
1
Объяснение при P = 3:
1. First iteration, we can remove element 1 with value `5`.
2. Second iteration, we can remove element 2 with `0`.
3. Third iteration, we can remove element 4 with value `2`.
Наконец, массив содержит только два элемента со значениями 1. Таким образом, количество оставшихся различных цветов равно 1.
Это код, который я пробовал, но застрял в том, как выполнить требования:
static int getDistinctFeatures(int[] array, int size, int K, int P) {
Map<Integer, Integer> map = new LinkedHashMap<>();
// Count the occurrence of each element in the array
for (int i : array) {
map.put(i, map.getOrDefault(i, 0) + 1);
}
Set<Integer> keys = map.keySet();
List<Integer> keyList = new ArrayList<>(keys);
int index = 0;
for (int i = 0; i < P && index < keyList.size(); i++) {
int key = keyList.get(index);
index++;
int count = map.get(key);
if (count == 1) {
map.remove(key);
} else {
// What to do here
}
}
return map.size();
}
@mahbubcseju, я тоже не уверен в этом входе, экзамен дал только 3 примера входных данных. Я пытался решить для них в первую очередь.




Вот предлагаемый подход.
value до count_of_valuek. Это count_incommensurate то, от скольких значений вы не можете избавиться.count_of_value / k.В вашем случае эти шаги приводят к следующему. Исходная карта:
{
0: 1,
1: 2,
2: 1,
5: 1,
}
Все значения делятся на k=1, поэтому count_incommensurate = 0.
Массив отсчетов в порядке возрастания равен [1, 1, 1, 2].
Теперь мы подошли к массиву поиска. Он начинается с 0 с общего количества отсчетов, которое равно 4. Итак [4, .... Теперь мы записываем каждое число количество раз, прежде чем уменьшить, и останавливаемся на 0. Таким образом, мы получаем [4, 3, 2, 1, 1]. Другими словами
counts: [1, 1, 1, 2 ]
lookup: [4, 3, 2, 1, 1]
Если бы наши подсчеты были [1, 2, 3], мы бы вместо этого получили
counts: [1, 2 , 3 ]
lookup: [3, 2, 2, 1, 1, 1]
Но вернемся к тому, что мы на самом деле получили. [4, 3, 2, 1, 1] — это массив, начинающийся с 0, для нашего поиска, а все, что находится за его пределами, — это 0.
Теперь делаем наши поиски.
Поиск 1 плюс несоизмеримое дает нам 3 + 0 = 3.
Поиск 5 не в конце, поэтому мы получаем 0 + 0 = 0.
Поиск 3 дает нам 1 + 0 = 1.
Если мы повторим это упражнение с k=2, мы обнаружим, что count_incommensurate — это 3, а наш поисковый массив окажется [1]. (После нулевых итераций элемент 1 все еще существует.) Поскольку все поиски не в конце, мы получим 3, 3, 3 в качестве нашего ответа.
Время для этого алгоритма O(N + Q). Учитывая, что для сканирования значений требуется O(N), а для сканирования запросов — O(Q), вы не можете улучшить это более чем на постоянный коэффициент. Небольшой момент, который следует упомянуть, заключается в том, что исходный массив счетчиков (в данном случае [1, 2, 1, 1]) необходимо отсортировать, что добавляет временную сложность O(N log N) к задаче.
Как генерируется массив [4, 3, 2, 1, 1], объясните, пожалуйста. Также я потерял и не смог понять пояснение под утверждением The lookup array is (remember it is a 0-based array) [4, 3, 2, 1, 1] как выполняются поиски 1, 5, 3 и почему мы добавляем их в несоизмеримые
Я имею в виду, что я не смог понять, как реализованы пункты 4 и 5.
@learner Я добавил больше объяснений того, как они были сделаны в этом случае, и как они были бы другими, если бы у нас был другой массив подсчетов. Надеюсь, это поможет.
Что касается того, почему мы добавляем несоизмеримое, то это потому, что мы НИКОГДА не избавляемся ни от одного из несоизмеримых элементов. Мы пытаемся удалить их, но в конечном итоге мы получаем остаток ниже k, который мы не можем удалить. Таким образом, мы отслеживаем, от скольких элементов мы можем избавиться, как быстро, и добавляем, из скольких мы убираем последний.
@btilly Не могли бы вы привести здесь код, который я пропустил, читая ваше объяснение.
@thealchemist Извините, я установил личную политику НЕ размещать код для чего-либо, что выглядит так, как будто оно исходит от онлайн-судьи.
Не знал, что это исходит от онлайн-судьи.
@thealchemist Я тоже не знаю, что это такое. Но формат вопроса, включая параметры, с которыми вы можете столкнуться, выглядит именно так.
Предложенное добавление от Ликантроп: Небольшой момент, который следует упомянуть, заключается в том, что первоначальный массив счетчиков (в данном случае [1, 2, 1, 1]) необходимо отсортировать, что добавляет к проблеме временную сложность O (N log N)`. (я: мне не понравилось должно быть, но теперь проверил ваше предложение: array of counts in increasing order — Lycanthropeus вполне может быть прав насчет оценки роста во время выполнения.)
@greybeard Каждый раз, когда вы выбираете k одного и того же значения и удаляете их. Если значение встречается несколько раз, не кратное k, вы никогда не сможете удалить его последнюю копию и, следовательно, не сможете удалить это значение из массива. И Ликантроп упустил что-то важное. Счетчики находятся в диапазоне 1..N, и может быть не более O(sqrt(N)) различных счетов. Сортировка ведром сортирует это в O(N).
Это ответ, который я закодировал на основе алгоритма, предложенного @btilly.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
class Main {
public static void main(String args[] ) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] num_arr;
num_arr = br.readLine().split("\\s");
int [] nkq_arr = new int[3];
for(int i=0;i<3;i++)
{
nkq_arr[i] = Integer.parseInt(num_arr[i]);
}
int N = nkq_arr[0];
int K = nkq_arr[1];
int Q = nkq_arr[2];
int i = 0,j = 0;
String[] param_arr;
param_arr = br.readLine().split("\\s");
int [] arr = new int[N];
while(i < N)
{
arr[i] = Integer.parseInt(param_arr[i]);
i++;
}
int[] queries = new int[Q];
while(j < Q)
{
queries[j] = Integer.parseInt(br.readLine());
j++;
}
for(int c=0;c<Q;c++)
{
System.out.println(minFeatures(arr,N,K,queries[c]));
}
}
static int minFeatures (int [] arr, int N, int K, int query)
{
HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
int count=0;
for(int i=0;i<N;i++)
{
if (!map.containsKey(arr[i]))
{
map.put(arr[i],1);
count++;
}
else
{
Integer b = map.get(arr[i]);
b+=1;
map.replace((Integer)arr[i],b);
}
}
List<Integer> relevant_arr = new ArrayList();
int improper_count=0;
int relevant_arr_length = 0;
for(Integer val : map.values())
{
if (val%K==0)
{
relevant_arr.add(val/K);
relevant_arr_length++;
}
else
{
improper_count++;
}
}
Collections.sort(relevant_arr);
List<Integer> lookUp_arr = new ArrayList();
int alpha = 0;
int overall_length=0;
while(alpha < relevant_arr_length)
{
int number_of_times = relevant_arr.get(alpha);
int beta = number_of_times;
while(beta > 0)
{
lookUp_arr.add(count);
beta--;
overall_length++;
}
count--;
alpha++;
}
if (query > overall_length-1)
{
return improper_count;
}
else
{
return improper_count + lookUp_arr.get(query);
}
}
}
Python Реализация алгоритма, предложенного @btilly.
from collections import defaultdict
def evaluateMin(arrQ,k,queryArr):
ans = []
countMap = defaultdict(lambda : 0)
for value in arrQ:
countMap[value] +=1
counts=[]
presentEveryTime = 0
for value in countMap:
if countMap[value] % k != 0:
presentEveryTime +=1
else:
counts.append(int(countMap[value]/k))
# Creating Lookup Array
counts = sorted(counts)
lookup = []
# print(counts)
appender = len(counts)
for count in counts:
for i in range(count):
lookup.append(appender)
if appender != 1:
appender -=1
# print(lookup,presentEveryTime)
for query in queryArr:
if query >= len(lookup):
ans.append(0+presentEveryTime)
else:
ans.append(lookup[query]+presentEveryTime)
return ans
print(evaluateMin([5,0,1,2,1,1,1],2,[1,5,3,0,2]))
Итак, если k = 2 и Array = [1,1,1,3,3,3], какой ответ будет для p = 1? Это 2?