You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ STL Map遍历执行erase操作时的索引异常问题排查

问题排查:LeetCode《Where Will the Ball Fall》迭代器异常问题

核心问题原因

你遇到的迭代器跳转异常,本质是遍历map时调用erase导致迭代器失效:

  • 当执行Balls.erase(i)后,当前迭代器i会变成无效状态,后续循环中的i++操作属于未定义行为,这就是处理完key=14后,迭代器未指向key=15反而出现异常跳转的原因。

修复方案(针对原代码)

修改遍历逻辑,利用map::erase的返回值——它会返回指向被删除元素下一个位置的有效迭代器,避免迭代器失效:

  1. 将原来的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);
}
  1. 额外性能优化:
    • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 20:11:09