
本文讲解一种优化的 arraylist 迭代处理方法:每次找出当前列表最小值,将其及左右相邻元素(边界处适当调整)移除,并将最小值累加到总和中,直至列表长度不足 1;重点修复原代码因未同步更新列表长度导致的无限循环问题。
本文讲解一种优化的 arraylist 迭代处理方法:每次找出当前列表最小值,将其及左右相邻元素(边界处适当调整)移除,并将最小值累加到总和中,直至列表长度不足 1;重点修复原代码因未同步更新列表长度导致的无限循环问题。
该问题看似简单,实则暗藏两个关键陷阱:索引偏移与循环终止条件失效。原始代码中虽定义了变量 l 表示当前列表长度,但在 remove() 操作后未在所有分支中及时更新 l,导致 while (l >= 1) 条件永远为真——尤其当 l == 2 时仅执行 ques.remove(index) 却遗漏 l--,造成死循环。
更严重的是,remove(int index) 会动态改变后续元素位置。例如在 [8,4,9,10,34,54,56] 中,min=4 位于索引 1,若先执行 ques.remove(0)(即删 8),则 4 将前移至索引 0,后续 remove(1) 就不再删 9,而是删 9 后的新元素,逻辑彻底错乱。因此必须严格按“先定位、再按相对顺序移除”原则操作,且每次移除后需立即更新 l。
以下是修正后的完整可运行代码(已通过测试,输出 68):
import java.util.*;
public class MinAdjacentRemoval {
public static void main(String[] args) {
List<Integer> ques = new ArrayList<>(Arrays.asList(8, 4, 9, 10, 34, 54, 56));
int l = ques.size();
int sum = 0;
while (l > 0) { // 建议改用 l > 0 更语义清晰(空列表即终止)
int min = Collections.min(ques);
sum += min;
int index = ques.indexOf(min);
// 根据 min 位置和剩余长度,安全移除对应元素
if (index == 0) {
ques.remove(0); // 移除 min(首元素)
if (l > 1) {
ques.remove(0); // 移除原 index+1(现首元素)
l -= 2;
} else {
l--;
}
} else if (index == l - 1) { // min 在末尾
ques.remove(index); // 移除 min
ques.remove(index - 1); // 移除左侧相邻
l -= 2;
} else { // min 在中间:移除 [index-1, index, index+1]
// 注意:必须从右向左删,避免索引偏移!
ques.remove(index + 1);
ques.remove(index);
ques.remove(index - 1);
l -= 3;
}
}
System.out.println(sum); // 输出:68
}
}✅ 关键优化点说明:
-
统一更新
l:每个remove分支均显式更新l,确保循环终将退出; -
安全删除顺序:当中间元素被删时,优先删除右侧索引较大者(如先
remove(index+1),再remove(index),最后remove(index-1)),防止左侧移除导致右侧索引失效; -
边界全覆盖:显式处理
index == 0(开头)、index == l-1(结尾)、以及中间三种情况,避免IndexOutOfBoundsException; -
语义化条件:将
while (l >= 1)改为while (l > 0),更符合“非空即处理”的业务逻辑。
⚠️ 注意事项:
-
Collections.min()和indexOf()时间复杂度均为 O(n),整体算法为 O(n²),对超大数据集建议改用堆或排序预处理; - 若要求稳定输出(如相同最小值取最左/最右),需自定义查找逻辑,而非依赖
indexOf()的首次匹配; - 生产环境应添加空列表校验与异常处理,增强鲁棒性。
通过以上重构,代码不仅正确输出 68,更具备可读性、健壮性与可维护性,是 ArrayList 动态操作类问题的标准实践范式。

















