打扰您,我需要实现一种算法,该算法可以简化为以下内容:
给定一个整数数组,所需的合并次数(表示为 k )返回合并数组的最大最小值,合并只能与相邻元素发生。
例如数组= [3,2,8,2,9]
,k = 2
两次合并后数组的最大最小值为5
,合并后的数组为[5, 10, 9]
。在此示例中,我们需要合并元素3
和2
以及8
和2
。
任何其他合并策略将产生的最小val小于或等于5
,例如:
[5,8,11]
,[3,10,11]
,[13,2,9]
(合并的元素可以再次合并)
什么是表示数据的最佳数据结构?什么是解决问题的有效算法?据我所知,在需要使用数组的当前最小值和其较小的相邻元素之一进行合并的地方,需要应用贪心算法。
编辑:我只是意识到贪婪算法可能不适用,对引起误导的评论表示抱歉,如果不能区分合并左元素还是右元素,这将产生错误的答案。以这个为例,给定一个数组= [4,5,3,5]
,我们需要删除2
元素。
贪婪的[4,5,3,5]
-> [4,8,5]
-> [12,5]
,答案是5
;但是正确的答案应该是8
,并具有以下合并顺序:
[4,5,3,5]
-> [4,5,8]
-> [9,8]
答案 0 :(得分:1)
ValPosFrom是一个简单的类,用于存储这些内容,from
是要合并的地方。您可以从List = 3,2,6,3,2和k = 1之类的东西获得不确定的结果,它将2分钟之一合并为5,但是哪一个无关紧要。当所有位置邻居的值都是唯一时,它会收敛。
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;
}