我想计算元素数量,如果符合标准则删除一些元素。删除使用collect和removeAll不起作用,因为它删除所有相同的元素,我想删除范围不是全部。 我尝试使用sublist.clear()但是我得到了ConcurrentModificationException,即使我使用它.remove()。
public static List<Integer> controlOccurrences(List<Integer> sortedArr, int m) {
int writelndex = 0, count=1;
List<List<Integer>> toRemove = new ArrayList<>();
for (int i = 1; i < sortedArr.size(); ++i) {
if (sortedArr.get(i-1).equals(sortedArr.get(i))) {
count++;
} else {
if(count == m) {
int nCopies = Math.min(2,m);
List<Integer> c = sortedArr.subList(writelndex + nCopies, i);
toRemove.add(c);
}
count = 1;
writelndex = i;
}
}
Iterator<List<Integer>> iterator = toRemove.iterator();
while (iterator.hasNext()) {
List<Integer> integers = iterator.next();
iterator.remove();
integers.clear();
}
return sortedArr;
}
编辑:添加一个例子:
假设我们有以下列表:(1,2,2,2,3,3,3,4,4,4,5,5)和m = 3.这意味着所有出现m次的数字都应该发生2次(Math.min(2,3))。所以预期的结果是(1,2,2,2,3,3,3,4,4,5,5)。
编辑2:@ShubhenduPramanik非常优雅地解决了这个任务。 但是,我仍然不清楚为什么抛出ConcurrentModificationException,即使我使用的是iterator.remove(),如何在迭代它时从列表中删除子列表。
答案 0 :(得分:2)
如果我正确理解了任务,那么算法:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) throws IOException {
int m = 3;
BufferedReader reader = new BufferedReader(
new InputStreamReader(System.in));
int numbers;
List<Integer> sortedList = new ArrayList<>();
// Fill in the list with values
for (int i = 0; i < 13; i++) {
numbers = Integer.parseInt(reader.readLine());
sortedList.add(numbers);
}
System.out.println(controlOccurrences(sortedList, m));
}
public static List<Integer> controlOccurrences(List<Integer> sortedArr, int m) {
int count= 1;
for (int i = 0; i < sortedArr.size(); i++) {
for (int j = 0; j < sortedArr.size(); j++) {
if (sortedArr.get(i).equals(sortedArr.get(j)) && i != j) {
count += 1;
}
}
if (count == m) {
sortedArr.remove(i);
count = 1;
} else {
count = 1;
}
}
return sortedArr;
}
}
答案 1 :(得分:2)
希望这会有所帮助:
static List<Integer> controlOccurrences(List<Integer> sortedArr, int m) {
//make the count of each element
Map<Integer, Long> result = sortedArr.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
for (Map.Entry<Integer, Long> entry : result.entrySet()) {
if (entry.getValue() == m) {
// Here 2 is hard coded. You can make a variable and pass it to the method with a parameter
for (int i = 0; i < m - 2; i++)
{
sortedArr.remove(entry.getKey());
}
}
}
return sortedArr;
}
N.B: 此代码并不完美,因为我假设m>=2
答案 2 :(得分:2)
要获得最优化的解决方案,您应该: 1.建立要删除的值的索引列表(或集) 2.将原始列表的值移动到新列表中,但列出的索引除外 3.返回新列表。
这样,您的算法复杂度为O(2n),比以前的答案都更优化。另外,您保持给定列表不变(可根据您的执行上下文推荐)。最后一个优点是,副本是受欢迎的,因为列表上的每个删除调用都可能很重(删除索引后的内部对象被移动到左侧:部分隐藏浏览-_-)
我不会直接给你一个有效的代码,让你练习;)。
注意:您的用例过于复杂,但您应该查看数组列表API的List.removeIf()代码,这是非常优化的。这是一篇关于它的文章:advantages of removeIf method