C++ STL Map遍历执行erase操作时的索引异常问题排查
问题排查:LeetCode《Where Will the Ball Fall》迭代器异常问题
核心问题原因
你遇到的迭代器跳转异常,本质是遍历map时调用erase导致迭代器失效:
- 当执行
Balls.erase(i)后,当前迭代器i会变成无效状态,后续循环中的i++操作属于未定义行为,这就是处理完key=14后,迭代器未指向key=15反而出现异常跳转的原因。
修复方案(针对原代码)
修改遍历逻辑,利用map::erase的返回值——它会返回指向被删除元素下一个位置的有效迭代器,避免迭代器失效:
- 将原来的
for循环改为while循环,手动控制迭代器递增:
auto i = Balls.begin(); while (i != Balls.end()) { cout << "Beginning: " << Balls.begin()->first << endl; int key = i->first; int m = i->second.first; int n = i->second.second; cout << "key: "<<i->first << " m: " << m << " n: " << n << endl; if(m >= grid.size()){ flag2 = false; break; } int state = grid[m][n]; bool stat = check_neigh(state, grid, m, n); if(stat == true){ i->second.first += 1; i->second.second += state; cout << "New key: "<<i->first << " m: " << i->second.first << " n: " << i->second.second << endl; i++; // 未删除元素时,手动递增迭代器 } else if(stat == false){ cout << "Deleted key: "<< i->first << endl; i = Balls.erase(i); // 用erase返回的有效迭代器更新i } display_map(Balls); }
- 额外性能优化:
check_neigh函数的参数vector<vector<int>> grid改为const vector<vector<int>>& grid,避免每次调用拷贝整个矩阵;display_map函数的参数改为const map<int, pair<int, int>>& m,避免不必要的容器拷贝。
更简洁的实现思路(推荐)
原代码用map维护小球状态的逻辑较复杂,可对每个小球单独模拟下落过程,完全避免迭代器问题,逻辑更清晰:
class Solution { public: bool check_neigh(int state, const vector<vector<int>>& grid, int i, int j) { int new_j = j + state; if (new_j < 0 || new_j >= grid[i].size()) return false; return state == grid[i][new_j]; } vector<int> findBall(vector<vector<int>>& grid) { int rows = grid.size(); int cols = grid[0].size(); vector<int> answer(cols, -1); // 逐个模拟每个小球的下落路径 for (int start_col = 0; start_col < cols; ++start_col) { int curr_row = 0; int curr_col = start_col; bool is_stuck = false; while (curr_row < rows) { int dir = grid[curr_row][curr_col]; // 检查是否能继续下落 if (!check_neigh(dir, grid, curr_row, curr_col)) { is_stuck = true; break; } // 移动到下一行的对应列 curr_col += dir; curr_row++; } // 未卡住则记录最终位置 if (!is_stuck) { answer[start_col] = curr_col; } } return answer; } };
这个实现直接遍历每个初始列的小球,逐行模拟下落,没有复杂的容器维护,时间复杂度为O(rows*cols),和原代码一致,但逻辑更易读,也不会出现迭代器相关的问题。
内容的提问来源于stack exchange,提问作者Sumedh
相关产品推荐
相关产品推荐

