代码随想录算法训练营 Day45 | 图论 part03

101. 孤岛的总面积

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被陆地单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。

现在你需要计算所有孤岛的总面积,岛屿面积的计算方式为组成岛屿的陆地的总数。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0。

输出描述

输出一个整数,表示所有孤岛的总面积,如果不存在孤岛,则输出 0。

输入示例

复制代码
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1

输出示例

复制代码
1
cpp 复制代码
// DFS
#include <iostream>
#include <vector>
using namespace std;

// 定义四个搜索方向:右、下、左、上
int dir[4][2]={0,1, 1,0, 0,-1, -1,0};
// DFS函数:从边界出发,将所有与边界相连的 '1' 染色(标记为已访问)
void dfs(vector<vector<int>>&graph, vector<vector<bool>>&visited, int x, int y){
    // 剪枝:如果已经访问过,或者当前格子是水域(0),直接返回
    if(visited[x][y] || graph[x][y]==0) return;
    // 标记当前陆地被访问
    visited[x][y]=true;
    // 向四个方向递归探索
    for(int i=0; i<4; i++){
        int curx = x + dir[i][0];
        int cruy = y + dir[i][1];
        // 边界合法性检查
        if(curx<0 || curx>=graph.size() || cruy<0 || cruy>=graph[0].size()) continue;
        // 递归进入下一层(注意:无需在此处判断是否为1或是否visited,因为递归函数入口会判断)
        dfs(graph, visited, curx, cruy);
    }
}

int main(){
    int n, m; 
    cin >> n >> m; // n为行数,m为列数
    vector<vector<int>> graph(n, vector<int>(m));
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    // 读取矩阵
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin >> graph[i][j];
        }
    }
    // 【核心逻辑1:从边界开始入侵】
    // 遍历左右两列边界
    for(int i=0; i<n; i++){
        if(graph[i][0]==1) dfs(graph, visited, i, 0);
        if(graph[i][m-1]==1) dfs(graph, visited, i, m-1);
    }
    // 遍历上下两行边界
    for(int j=0; j<m; j++){
        if(graph[0][j]==1) dfs(graph, visited, 0, j);
        if(graph[n-1][j]==1) dfs(graph, visited, n-1, j);
    }
    // 【核心逻辑2:统计剩余的封闭岛屿】
    int res=0;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            // 如果是陆地(1),且没有被边界污染(未访问),说明它是一个封闭岛屿
            if(!visited[i][j] && graph[i][j]==1){
                res++;
            }
        }
    }
    cout << res << endl;
    return 0;
}


// BFS
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

// 定义四个搜索方向:右、下、左、上
int dir[4][2]={0,1, 1,0, 0,-1, -1,0};
// BFS函数:利用队列,将所有与边界相连的 '1' 染色(标记为已访问)
void bfs(vector<vector<int>>&graph, vector<vector<bool>>&visited, int x, int y){
    queue<pair<int,int>> que;
    que.push({x,y});
    visited[x][y]=true; // 入队时即刻标记,防止同一节点被重复推入队列
    while(!que.empty()){
        pair<int,int> cur = que.front(); 
        que.pop();
        // 探索当前节点四个方向
        for(int i=0; i<4; i++){
            int curx = cur.first + dir[i][0];
            int cruy = cur.second + dir[i][1];
            // 边界合法性检查
            if(curx<0 || curx>=graph.size() || cruy<0 || cruy>=graph[0].size()) continue;
            // 如果是未访问过的陆地,加入队列并标记
            if(!visited[curx][cruy] && graph[curx][cruy]==1){
                que.push({curx, cruy});
                visited[curx][cruy]=true;
            }
        }
    }
}

int main(){
    int n, m; 
    cin >> n >> m; // n为行数,m为列数
    vector<vector<int>> graph(n, vector<int>(m));
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    // 读取矩阵
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            cin >> graph[i][j];
        }
    }
    // 【核心逻辑1:从边界开始入侵】
    // 遍历左右两列边界
    for(int i=0; i<n; i++){
        if(graph[i][0]==1) bfs(graph, visited, i, 0);
        if(graph[i][m-1]==1) bfs(graph, visited, i, m-1);
    }
    // 遍历上下两行边界
    for(int j=0; j<m; j++){
        if(graph[0][j]==1) bfs(graph, visited, 0, j);
        if(graph[n-1][j]==1) bfs(graph, visited, n-1, j);
    }
    // 【核心逻辑2:统计剩余的封闭岛屿】
    int res=0;
    for(int i=0; i<n; i++){
        for(int j=0; j<m; j++){
            // 如果是陆地(1),且没有被边界污染(未访问),说明它是一个封闭岛屿
            if(!visited[i][j] && graph[i][j]==1){
                res++;
            }
        }
    }
    cout << res << endl;
    return 0;
}

总结

1. 核心思想

本题不是直接找孤岛,而是反向思考:

先从地图四条边界上的陆地出发,把所有和边界连通的陆地都标记掉。

最后剩下没有被访问过的陆地,就是孤岛陆地。

2. DFS 和 BFS 的区别
  • DFS:递归向四周搜索,代码更简洁。
  • BFS:用队列一层一层扩展,不容易出现递归爆栈问题。

两种方法本质一样,都是为了标记边界连通块。

3. 复杂度分析
  • 时间复杂度:O(n * m)
  • 空间复杂度:O(n * m)

102. 沉没孤岛

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,岛屿指的是由水平或垂直方向上相邻的陆地单元格组成的区域,且完全被水域单元格包围。孤岛是那些位于矩阵内部、所有单元格都不接触边缘的岛屿。

现在你需要将所有孤岛"沉没",即将孤岛中的所有陆地单元格(1)转变为水域单元格(0)。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。

之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。

输出描述

输出将孤岛"沉没"之后的岛屿矩阵。 注意:每个元素后面都有一个空格

输入示例

复制代码
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1

输出示例

复制代码
1 1 0 0 0
1 1 0 0 0
0 0 0 0 0
0 0 0 1 1
cpp 复制代码
// DFS
#include <iostream>
#include <vector>
using namespace std;

// 四个方向:右、下、左、上
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
// DFS:把和边界连通的陆地标记为 2
void dfs(vector<vector<int>>& graph, int x, int y) {
    // 遇到海洋或已经标记过的陆地,直接返回
    if (graph[x][y] == 0 || graph[x][y] == 2) return;
    // 将当前位置标记为 2
    graph[x][y] = 2;
    // 向四个方向搜索
    for (int i = 0; i < 4; i++) {
        int curx = x + dir[i][0];
        int cruy = y + dir[i][1];
        // 越界则跳过
        if (curx < 0 || curx >= graph.size() ||
            cruy < 0 || cruy >= graph[0].size()) {
            continue;
        }
        dfs(graph, curx, cruy);
    }
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> graph(n, vector<int>(m));
    // 输入地图
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> graph[i][j];
        }
    }
    // 从左右边界的陆地开始搜索
    for (int i = 0; i < n; i++) {
        if (graph[i][0] == 1) dfs(graph, i, 0);
        if (graph[i][m - 1] == 1) dfs(graph, i, m - 1);
    }
    // 从上下边界的陆地开始搜索
    for (int j = 0; j < m; j++) {
        if (graph[0][j] == 1) dfs(graph, 0, j);
        if (graph[n - 1][j] == 1) dfs(graph, n - 1, j);
    }
    // 输出结果:
    // 标记为 2 的位置说明和边界连通,输出 1
    // 其他位置输出 0
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (graph[i][j] == 2) cout << 1 << " ";
            else cout << 0 << " ";
        }
        cout << endl;
    }
    return 0;
}


// BFS
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

// 四个方向:右、下、左、上
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
// BFS:把和边界连通的陆地标记为 2
void bfs(vector<vector<int>>& graph, int x, int y) {
    queue<pair<int, int>> que;
    // 起点入队,并标记
    que.push({x, y});
    graph[x][y] = 2;
    while (!que.empty()) {
        pair<int, int> cur = que.front();
        que.pop();
        // 向四个方向扩展
        for (int i = 0; i < 4; i++) {
            int curx = cur.first + dir[i][0];
            int cruy = cur.second + dir[i][1];
            // 越界则跳过
            if (curx < 0 || curx >= graph.size() ||
                cruy < 0 || cruy >= graph[0].size()) {
                continue;
            }
            // 如果是未标记的陆地,加入队列
            if (graph[curx][cruy] == 1) {
                que.push({curx, cruy});
                graph[curx][cruy] = 2;
            }
        }
    }
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> graph(n, vector<int>(m));
    // 输入地图
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> graph[i][j];
        }
    }
    // 从左右边界的陆地开始搜索
    for (int i = 0; i < n; i++) {
        if (graph[i][0] == 1) bfs(graph, i, 0);
        if (graph[i][m - 1] == 1) bfs(graph, i, m - 1);
    }
    // 从上下边界的陆地开始搜索
    for (int j = 0; j < m; j++) {
        if (graph[0][j] == 1) bfs(graph, 0, j);
        if (graph[n - 1][j] == 1) bfs(graph, n - 1, j);
    }
    // 输出结果:
    // 只有和边界连通的陆地输出 1
    // 其他位置输出 0
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (graph[i][j] == 2) cout << 1 << " ";
            else cout << 0 << " ";
        }
        cout << endl;
    }
    return 0;
}

总结

1. 核心思路

采用反向思维:

  1. 从地图四条边界出发
  2. 遇到陆地(1)就进行 DFS / BFS
  3. 将所有能连通到的陆地标记为 2
  4. 最后遍历输出:
    • 2 → 1(保留)
    • 其他 → 0

本质是:
先标记"安全区域",再统一处理结果

2. DFS 与 BFS

两种方法本质完全一致,区别仅在实现方式:

  • DFS:递归实现,代码简洁
  • BFS:队列实现,更稳定,不依赖递归深度

在数据规模较大时,BFS 更安全

3. 和常见"孤岛问题"的区别
  • 孤岛问题:统计不与边界连通的陆地数量
  • 本题:直接保留与边界连通的陆地

实现上的区别:

  • 孤岛问题:通常使用 visited 数组
  • 本题:直接修改原数组(1 → 2)
4. 复杂度分析
  • 时间复杂度:O(n * m)
  • 空间复杂度:
    • DFS:递归栈空间
    • BFS:队列空间

103. 高山流水

题目描述

现有一个 N × M 的矩阵,每个单元格包含一个数值,这个数值代表该位置的相对高度。矩阵的左边界和上边界被认为是第一组边界,而矩阵的右边界和下边界被视为第二组边界。

矩阵模拟了一个地形,当雨水落在上面时,水会根据地形的倾斜向低处流动,但只能从较高或等高的地点流向较低或等高并且相邻(上下左右方向)的地点。我们的目标是确定那些单元格,从这些单元格出发的水可以达到第一组边界和第二组边界。

输入描述

第一行包含两个整数 N 和 M,分别表示矩阵的行数和列数。

后续 N 行,每行包含 M 个整数,表示矩阵中的每个单元格的高度。

输出描述

输出共有多行,每行输出两个整数,用一个空格隔开,表示可达第一组边界和第二组边界的单元格的坐标,输出顺序任意。

输入示例

复制代码
5 5
1 3 1 2 4
1 2 1 3 2
2 4 7 2 1
4 5 6 1 1
1 4 1 2 1

输出示例

复制代码
0 4
1 3
2 2
3 0
3 1
3 2
4 0
4 1
cpp 复制代码
// DFS
#include <iostream>
#include <vector>
using namespace std;

// 四个方向:右、下、左、上
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
// 从边界开始反向搜索
// border 用来记录当前点是否可以到达某一边界
void dfs(vector<vector<int>>& graph, vector<vector<bool>>& border, int x, int y) {
    // 如果已经访问过,直接返回
    if (border[x][y]) return;
    // 标记当前位置可以到达该边界
    border[x][y] = true;
    // 向四个方向搜索
    for (int i = 0; i < 4; i++) {
        int curx = x + dir[i][0];
        int cruy = y + dir[i][1];
        // 越界则跳过
        if (curx < 0 || curx >= graph.size() ||
            cruy < 0 || cruy >= graph[0].size()) {
            continue;
        }
        // 反向搜索:
        // 只有相邻位置高度 >= 当前高度时,才可以继续走
        if (graph[x][y] <= graph[curx][cruy]) {
            dfs(graph, border, curx, cruy);
        }
    }
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> graph(n, vector<int>(m));
    // leftBorder:能流到左边界或上边界的点
    vector<vector<bool>> leftBorder(n, vector<bool>(m, false));
    // rightBorder:能流到右边界或下边界的点
    vector<vector<bool>> rightBorder(n, vector<bool>(m, false));
    // 输入高度矩阵
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> graph[i][j];
        }
    }
    // 从左右边界开始搜索
    for (int i = 0; i < n; i++) {
        dfs(graph, leftBorder, i, 0);       // 左边界
        dfs(graph, rightBorder, i, m - 1);  // 右边界
    }
    // 从上下边界开始搜索
    for (int j = 0; j < m; j++) {
        dfs(graph, leftBorder, 0, j);       // 上边界
        dfs(graph, rightBorder, n - 1, j);  // 下边界
    }
    // 同时能到达两类边界的点,就是答案
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (leftBorder[i][j] && rightBorder[i][j]) {
                cout << i << " " << j << endl;
            }
        }
    
    return 0;
}


// BFS
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

// 四个方向:右、下、左、上
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
// 从边界开始反向搜索
// border 用来记录当前点是否可以到达某一边界
void bfs(vector<vector<int>>& graph, vector<vector<bool>>& border, int x, int y) {
    queue<pair<int, int>> que;
    // 起点入队,并标记
    que.push({x, y});
    border[x][y] = true;
    while (!que.empty()) {
        pair<int, int> cur = que.front();
        que.pop();
        // 向四个方向扩展
        for (int i = 0; i < 4; i++) {
            int curx = cur.first + dir[i][0];
            int cruy = cur.second + dir[i][1];
            // 越界则跳过
            if (curx < 0 || curx >= graph.size() ||
                cruy < 0 || cruy >= graph[0].size()) {
                continue;
            }
            // 反向搜索:
            // 只有相邻位置高度 >= 当前高度,才能继续扩展
            if (graph[cur.first][cur.second] <= graph[curx][cruy] &&
                !border[curx][cruy]) {
                que.push({curx, cruy});
                border[curx][cruy] = true;
            }
        }
    }
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> graph(n, vector<int>(m));
    // leftBorder:能流到左边界或上边界的点
    vector<vector<bool>> leftBorder(n, vector<bool>(m, false));
    // rightBorder:能流到右边界或下边界的点
    vector<vector<bool>> rightBorder(n, vector<bool>(m, false));
    // 输入高度矩阵
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> graph[i][j];
        }
    }
    // 从左右边界开始搜索
    for (int i = 0; i < n; i++) {
        bfs(graph, leftBorder, i, 0);       // 左边界
        bfs(graph, rightBorder, i, m - 1);  // 右边界
    }
    // 从上下边界开始搜索
    for (int j = 0; j < m; j++) {
        bfs(graph, leftBorder, 0, j);       // 上边界
        bfs(graph, rightBorder, n - 1, j);  // 下边界
    }
    // 同时能到达两类边界的点,就是答案
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (leftBorder[i][j] && rightBorder[i][j]) {
                cout << i << " " << j << endl;
            }
        }
    }
    return 0;
}

总结

1. 核心思路

这题的关键是 反向搜索

正常想法是从每个点出发,看它能不能流到两类边界,但这样会重复搜索很多次。

更好的做法是:

  • 从左边界、上边界出发,找出所有能到达第一类边界的点
  • 从右边界、下边界出发,找出所有能到达第二类边界的点
  • 最后取两个结果的交集

也就是:

复制代码
leftBorder[i][j] && rightBorder[i][j]

满足这个条件的点,就是答案。

2. 为什么要反向搜索

水流的方向是从高处流向低处。

如果从边界反向搜索,那么只能从低处往高处走,所以判断条件是:

复制代码
graph[当前点] <= graph[下一个点]

这样找到的点,表示它们的水可以顺着高度下降流回边界。

3. DFS 与 BFS

两种方法思路一样:

  • DFS:递归搜索,写法简洁
  • BFS:队列搜索,更稳定

本题本质上都是从边界进行图的遍历。

4. 复杂度分析
  • 时间复杂度:O(n * m)
  • 空间复杂度:O(n * m)

104. 建造最大岛屿

题目描述

给定一个由 1(陆地)和 0(水)组成的矩阵,你最多可以将矩阵中的一格水变为一块陆地,在执行了此操作之后,矩阵中最大的岛屿面积是多少。

岛屿面积的计算方式为组成岛屿的陆地的总数。岛屿是被水包围,并且通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设矩阵外均被水包围。

输入描述

第一行包含两个整数 N, M,表示矩阵的行数和列数。之后 N 行,每行包含 M 个数字,数字为 1 或者 0,表示岛屿的单元格。

输出描述

输出一个整数,表示最大的岛屿面积。

输入示例

复制代码
4 5
1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1

输出示例

复制代码
6
cpp 复制代码
#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>
using namespace std;

int cnt; // 记录当前岛屿的面积
// 四个方向:右、下、左、上
int dir[4][2] = {0, 1, 1, 0, 0, -1, -1, 0};
// DFS:给同一个岛屿的所有陆地打上相同编号 mark
void dfs(vector<vector<int>>& graph,
         vector<vector<bool>>& visited,
         int x,
         int y,
         int mark) {
    // 如果已经访问过,或者当前位置是海洋,直接返回
    if (visited[x][y] || graph[x][y] == 0) return;
    // 标记当前位置已经访问
    visited[x][y] = true;
    // 将当前陆地改成岛屿编号
    graph[x][y] = mark;
    // 当前岛屿面积加一
    cnt++;
    // 向四个方向搜索
    for (int i = 0; i < 4; i++) {
        int curx = x + dir[i][0];
        int cruy = y + dir[i][1];
        // 越界则跳过
        if (curx < 0 || curx >= graph.size() ||
            cruy < 0 || cruy >= graph[0].size()) {
            continue;
        }
        dfs(graph, visited, curx, cruy, mark);
    }
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<int>> graph(n, vector<int>(m));
    vector<vector<bool>> visited(n, vector<bool>(m, false));
    // key:岛屿编号
    // value:该岛屿的面积
    unordered_map<int, int> ump;
    // 输入地图
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> graph[i][j];
        }
    }
    int mark = 2;      // 岛屿编号从 2 开始,避免和 0、1 冲突
    bool isAll = true; // 判断是否全是陆地
    // 第一次遍历:给每个岛屿编号,并记录面积
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            // 只要存在海洋,就不是全陆地
            if (graph[i][j] == 0) isAll = false;
            // 遇到未访问过的陆地,就搜索整座岛
            if (!visited[i][j] && graph[i][j] == 1) {
                cnt = 0;
                dfs(graph, visited, i, j, mark);
                // 记录当前编号对应的岛屿面积
                ump[mark++] = cnt;
            }
        }
    }
    // 如果全是陆地,最大面积就是整个矩阵大小
    if (isAll) {
        cout << n * m << endl;
        return 0;
    }
    int res = 0;
    // 用来去重,防止同一个岛屿被重复累加
    unordered_set<int> ust;
    // 第二次遍历:尝试把每一个 0 变成 1
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (graph[i][j] == 0) {
                int sum = 1; // 当前 0 变成 1,所以初始面积为 1
                ust.clear();
                // 查看这个 0 周围四个方向连接了哪些岛屿
                for (int k = 0; k < 4; k++) {
                    int curx = i + dir[k][0];
                    int cruy = j + dir[k][1];
                    // 越界则跳过
                    if (curx < 0 || curx >= n ||
                        cruy < 0 || cruy >= m) {
                        continue;
                    }
                    // 如果该岛屿没有被统计过,并且编号存在于 map 中
                    if (ust.find(graph[curx][cruy]) == ust.end() &&
                        ump.find(graph[curx][cruy]) != ump.end()) {
                        ust.insert(graph[curx][cruy]);
                        sum += ump[graph[curx][cruy]];
                    }
                }
                // 更新最大岛屿面积
                res = max(res, sum);
            }
        }
    }
    cout << res << endl;
    return 0;
}

总结

1. 核心思路

这题的关键是:先给每个岛屿编号,再枚举每个海洋格子

第一次遍历矩阵时,遇到陆地就用 DFS 搜索整座岛屿,把同一座岛都标记成同一个 mark,并用 unordered_map 记录该岛屿的面积。

第二次遍历矩阵时,尝试把每个 0 变成 1,然后统计它四周能连接到哪些岛屿,计算合并后的最大面积。

2. 为什么 mark 从 2 开始

原图中:

复制代码
0 表示海洋
1 表示未编号的陆地

所以岛屿编号从 2 开始,可以避免和原来的 01 冲突。

3. 去重的作用

一个海洋格子四周可能有多个方向连接到同一座岛。

所以需要用 unordered_set 去重,防止同一个岛屿面积被重复累加。

4. 特殊情况

如果整个矩阵全是陆地,那么不需要修改任何位置,最大岛屿面积就是:

复制代码
n * m
5. 复杂度分析
  • 时间复杂度:O(n * m)
  • 空间复杂度:O(n * m)
相关推荐
Gh0st_Lx2 小时前
【8】分类任务原理
算法·分类·数据挖掘
a里啊里啊2 小时前
软考-软件评测师:知识点整理(六)——数据结构与算法
数据结构·算法·链表·软考·软件评测师
想带你从多云到转晴2 小时前
06、数据结构与算法---二叉树
java·数据结构·算法
酉鬼女又兒2 小时前
Leetcode 26.删除有序数组中的重复项 双指针巧解有序数组去重:从快慢指针到原地修改算法的精髓
java·数据结构·算法·leetcode·职场和发展·蓝桥杯·排序算法
承渊政道2 小时前
【动态规划算法】(斐波那契数列模型详解)
数据结构·c++·学习·算法·leetcode·macos·动态规划
笨笨饿2 小时前
# 67_MCU的几大分区
数据结构·单片机·嵌入式硬件·算法·机器人·线性回归·个人开发
6Hzlia2 小时前
【Hot 100 刷题计划】 LeetCode 230. 二叉搜索树中第 K 小的元素 | C++ 栈迭代中序遍历
c++·算法·leetcode
大熊背2 小时前
ISP Pipeline中Lv实现方式探究之六--lv值计算再优化
网络·算法·自动曝光·lv
RTC老炮2 小时前
WebRTC下FlexFEC算法架构及原理
网络·算法·音视频·webrtc