重新排序数组s.t.组中没有重复项

时间:2014-01-28 18:12:38

标签: arrays algorithm

所以我正在努力解决以下面试问题:

/** Given an unordered array of positive integers, create an algorithm that makes sure
no group of integers of size bigger than M have the same integers. 

Input: 2,1,1,1,3,4,4,4,5 M = 2 
Output: 2,1,1,3,1,4,4,5,4
*/

我想到了一个O(n ^ 2)解决方案:遍历数组并交换给定组中重复的相邻项。但是因为你有1,2,3,4,1,1 M = 2这样的情况,你必须在数组的后面环绕n次,给你多项式时间。

所以我有以下解决方案,它应该在线性时间内运行:

public static int[] regroup(int[] input, int m) {
    HashMap<Integer, Integer> map = new HashMap<>();
    for (int i : input) {
        if (!map.containsKey(i)) {
            map.put(i, 1);
        } else {
            map.put(i, map.get(i) + 1);
        }
    }
    int i = 0, n = 0;
    while (i < input.length) {
        for (int curr : map.keySet()) {
           if (n == m) { 
               n = 0;
               break;
           }
           if (map.get(curr) > 0) {
               input[i] = curr;
               map.put(curr, map.get(curr) - 1);
               i++; n++;
           } else {
               continue;
           }
        }     
    }
    return input;
}

这实际上使得hashmap具有其出现次数的所有值,然后从每个桶中为每个M大小的组中选择一个项目,从而保证唯一的项目。虽然我遇到的问题是以下反例:

{2,1,1,1,3,4,4,4,5} M = 3

返回

[1, 2, 3, 1, 4, 5, 1, 4, 4]

这显然是不对的。发生了什么事情就是用尽了最后一个选择的独特项目,所以只需将4两次放入最后一组。谁能想到解决这个问题并保持线性时间的方法?

1 个答案:

答案 0 :(得分:1)

计算完所有元素后,将它们放入堆中(数字,计数)。 从堆中取一对并开始在输入数组中分配它们,差值为M,直到到达输入数组的末尾。到达阵列末尾后,从上一次开始的阵列开始下一个位置。代码段如下:

     int curr = 0;
     int start = curr;
     while(maxHeap.size() > 0){
            Pair p = maxHeap.poll();
            int i =0;
            while(i < p.count){
                input[start] = p.num;
// keep putting element at gap of m
                start = start + m;
// if exceeded the length of input array , wrap around with previous start +1.
                if(start >= input.length){
                    curr++;
                    start = current;
                }
                i++;
            }
        }
        return true;
    }