删除给定迭代次数的元素

时间:2019-07-01 23:54:29

标签: java algorithm

给出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();
}

3 个答案:

答案 0 :(得分:1)

这是一种建议的方法。

  1. 构建从valuecount_of_value的地图
  2. 找出没有被k整除的计数值。 count_incommensurate是您无法摆脱的几个值。
  3. 对于其余值,通过递增计数来创建count_of_value / k的数组。
  4. 现在创建一个按迭代次数查找有多少个可删除值的查询。
  5. 执行查询。

对于您而言,这些步骤将导致以下结果。初始地图为:

{
    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 = 0

如果我们用k=2重复此练习,我们会发现count_incommensurate3,并且查找数组最终变成了[1]。 (经过零次迭代后,元素1仍然存在。)由于所有查找都已结束,因此我们将以3, 3, 3作为答案。

此算法的时间为O(N + Q)。鉴于需要O(N)来扫描值,以及O(Q)来扫描查询,因此您在此方面的改进不能超过一个恒定的因素。

答案 1 :(得分:1)

这是我根据@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);
      }
  }
}

答案 2 :(得分:0)

@btilly 建议的算法的 Python 实现。

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]))