3

excuse me for the confusing title, I need to implement an algorithm which can be simplified as the following:

given an array of integers, and the number of merges needed (denoted as k), return the maximum min value of the merged array, a merge can only happen with adjacent elements.

E.g. array = [3,2,8,2,9], k = 2 The maximum min value of the array after two merges is 5, and the merged array is [5, 10, 9]. In this example, we need to merge elements 3 & 2 and 8 & 2.

Any other merge strategies will yield min val that is smaller or equal to 5, e.g.: [5,8,11], [3,10,11], [13,2,9](merged elements can be merged again)

What is the best data structure to represent the data and what is an efficient algorithm to address the problem? As far as I can think of, a greedy algorithm needs to be applied where a merge needs to happen with the current min value of the array and one of its smaller neighboring element.

Edit: I just realized that greedy algorithm might not apply, sorry for the misleading comment, if it doesn't distinguish between merging with left or right elements, this will generate the wrong answer. Take this as an example, given an array = [4,5,3,5], and we need to remove 2 elements.

With greedy, [4,5,3,5] -> [4,8,5] -> [12,5], so the answer is 5; however the correct answer should be 8 with the following merge sequence:

[4,5,3,5] -> [4,5,8] -> [9,8]

Chen Xie
  • 3,849
  • 8
  • 27
  • 46
  • 2
    it seems that `[5, 10, 9]` and `[5,8,11]` both have min of 5? But it seems like the alg is get smallest number in list and remove. add it to the least of it's neighbors. repeat for k itterations. and you can use an ArrayList easiest probably. – mavriksc Jan 10 '19 at 22:54

1 Answers1

1

ValPosFrom is a simple class that stores those things, from being the place to merge from . you can get non deterministic results from things like List = 3,2,6,3,2 and k=1 it will merge one of the 2 mins to 5 but it doesn't matter which one. it converges when all of any positions neighbors values are unique.

    private static List<Integer> merge(List<Integer> things, int merges) {
    List<Integer> result = new ArrayList<>(things);
    for (int i = 0; i < merges; i++) {
        int min = Integer.MAX_VALUE;
        List<Integer> positions = new ArrayList<>();
        for (int j = 0; j < result.size(); j++) {
            if (result.get(j) < min) {
                positions.clear();
                positions.add(j);
                min = result.get(j);
            } else if (result.get(j) == min) {
                positions.add(j);
            }
        }
        List<ValPosFrom> neighbors = new ArrayList<>();
        positions.forEach(p -> {
            if (p - 1 >= 0) {
                neighbors.add(new ValPosFrom(result.get(p - 1), p - 1, p));
            }
            if (p + 1 < result.size()) {
                neighbors.add(new ValPosFrom(result.get(p + 1), p + 1, p));
            }
        });
        ValPosFrom vpf = Collections.min(neighbors, Comparator.comparingInt(v -> v.val));
        result.set(vpf.pos, result.get(vpf.pos) + result.get(vpf.from));
        result.remove(vpf.from);
    }
    return result;
}
mavriksc
  • 1,130
  • 1
  • 7
  • 10