Leetcode brushing notes (C++) - deep search wide search

Leetcode brushing notes (C++) - deep search wide search

Sort out the ideas in the process of brushing the questions, and summarize and share them here.
github address: https://github.com/lvjian0706/Leetcode-solutions
The github project is just newly created, and the organized code and ideas will be uploaded one after another. The code is based on C++ and python. At the same time, the basic sorting algorithm will also be sorted and uploaded.

133. Clone Map

Given a reference to a node in an undirected connected graph, you are asked to return a deep copy (clone) of that graph.

Each node in the graph contains its value val (int) and a list of its neighbors (list[Node]).

class Node {
public int val;
public List neighbors;
}

Test case format:

For simplicity, each node's value is the same as its index. For example, the first node has value 1 (val = 1), the second node has value 2 (val = 2), and so on. The graph is represented using an adjacency list in the test cases.

Adjacency lists are collections of unordered lists used to represent finite graphs. Each list describes the set of neighbors of a node in the graph.

The given node will always be the first node in the graph (with value 1). You must return a copy of the given node as a reference to the cloned graph.

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> neighbors;
    
    Node() {
        val = 0;
        neighbors = vector<Node*>();
    }
    
    Node(int _val) {
        val = _val;
        neighbors = vector<Node*>();
    }
    
    Node(int _val, vector<Node*> _neighbors) {
        val = _val;
        neighbors = _neighbors;
    }
};
*/

class Solution {
    
    
public:
    /*
    使用哈希表visited进行深度遍历,深度遍历实际上就是递归遍历图中节点:
    1. 当遍历到的节点为空时,返回NULL;
    2. 当遍历到的节点已被访问过,直接返回使用该节点创建的新节点;
    3. 否则,使用该节点创建新节点,并在visited中进行标记:
    3.1 新节点的值为原始节点的值;
    3.2 新节点的邻接列表为与原始节点的邻接列表中的节点一一对应的新节点,在对应过程中,如果不存在该节点,递归调用DFS进行创建,如果存在,则为情况2,直接返回该新节点;
    */
    Node* DFS(Node* node, map<Node*, Node*> &visited){
    
    
        if(!node) return NULL;
        /*
        count()为在哈希表中统计个数的方法,可用于判断是否存在该键
        */
        if(visited.count(node)) return visited[node];
        Node* new_node = new Node(node->val);
        visited[node] = new_node;
        for(int i=0; i<node->neighbors.size(); i++){
    
    
            new_node->neighbors.push_back(DFS(node->neighbors[i], visited));
        }
        return new_node;
    }

    /*
    图的克隆过程其实就是图的遍历过程,因此可以使用DFS或BFS,又因为图为无向连通图,为了避免重复遍历节点,使用哈希表记录已访问节点;
    由于是做深拷贝,所以哈希表中键值对分别为原节点:新节点,用于返回新节点;
    */
    Node* cloneGraph(Node* node) {
    
    
        map<Node*, Node*> visited;
        return DFS(node, visited);
    }
};


/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> neighbors;
    
    Node() {
        val = 0;
        neighbors = vector<Node*>();
    }
    
    Node(int _val) {
        val = _val;
        neighbors = vector<Node*>();
    }
    
    Node(int _val, vector<Node*> _neighbors) {
        val = _val;
        neighbors = _neighbors;
    }
};
*/

class Solution {
    
    
public:
    /*
    使用哈希表visited进行广度遍历:
    1. 当节点为空时,返回NULL;
    2. 定义队列用来存储当前访问的节点,并将当前节点push进队列中;
    3. 将当前节点作为键,使用当前节点创建的新节点作为值存入visited(新节点的邻接列表先不管);
    4. 当队列不为空时,循环遍历队列中的节点:
    4.1 取出队头元素,循环遍历队头结点的邻接节点:
    4.1.1 当节点没有访问过时,创建新节点,将原节点push到队列中,并在visited中进行标记;(由于是先创建后标记,所以可以保证visited中的每一个键节点对应的值节点都已经被创建过)
    4.1.2 将队头结点对应的新节点的邻接节点赋值为队头结点的邻接节点对应的新节点;
    */
    Node* DFS(Node* node, map<Node*, Node*> &visited){
    
    
        if(!node) return NULL;
        queue<Node*> nodeQ;
        nodeQ.push(node);
        Node* new_node = new Node(node->val);
        visited[node] = new_node;
        while(!nodeQ.empty()){
    
    
            Node* temp = nodeQ.front();
            nodeQ.pop();
            for(int i=0; i<temp->neighbors.size(); i++){
    
    
                if(!visited.count(temp->neighbors[i])){
    
    
                    Node* new_temp = new Node(temp->neighbors[i]->val);
                    visited[temp->neighbors[i]] = new_temp;
                    nodeQ.push(temp->neighbors[i]);
                }
                visited[temp]->neighbors.push_back(visited[temp->neighbors[i]]);
            }
        }
        return new_node;
    }

    /*
    图的克隆过程其实就是图的遍历过程,因此可以使用DFS或BFS,又因为图为无向连通图,为了避免重复遍历节点,使用哈希表记录已访问节点;
    由于是做深拷贝,所以哈希表中键值对分别为原节点:新节点,用于返回新节点;
    */
    Node* cloneGraph(Node* node) {
    
    
        map<Node*, Node*> visited;
        return DFS(node, visited);
    }
};

200. Number of islands

Given a 2D grid consisting of '1' (land) and '0' (water), please count the number of islands in the grid.

Islands are always surrounded by water, and each island can only be formed by joining horizontally or vertically adjacent land.

Also, you can assume that the mesh is surrounded by water on all four sides.

Example 1:
Input:
[
['1','1','1','1','0'],
['1','1','0','1','0'],
['1','1','0','0','0'], [
'0','0','0','0','0'] ]
Output
: 1
Example 2:
Input:
[
['1','1','0','0','0'],
['1','1','0','0','0'],
['0 ','0','1','0','0'],
['0','0','0','1','1'] ]
Output
: 3
Explanation: Each island only Can be formed by connecting horizontally and/or vertically adjacent land.

class Solution {
    
    
public:
    /*
    深度遍历grid:
    1. 定义坐标偏移量dx,dy,在遍历过程中,使用x+dx,y+dy来定义四个方向的相邻位置;
    2. 将visited中此时遍历到的位置赋为1;
    3. 循环遍历相邻的4个位置,当相邻点为1且visited中对应点为0时,可以从该相邻点继续进行递归遍历;
    */
    void DFS(vector<vector<char>>& grid, vector<vector<int>> &visited, int x, int y){
    
    
        vector<int> dx = {
    
    0, 0, -1, 1};
        vector<int> dy = {
    
    -1, 1, 0, 0};
        visited[x][y] = 1;
        for(int i=0; i<4; i++){
    
    
            int new_x = x + dx[i];
            int new_y = y + dy[i];
            /*
            判断是否越界
            */
            if(new_x >= 0 && new_x <= grid.size()-1 && new_y >= 0 && new_y <= grid[0].size()-1){
    
    
                if(grid[new_x][new_y]=='1' && visited[new_x][new_y]==0){
    
    
                    DFS(grid, visited, new_x, new_y);
                }
            }
        }
    }

    /*
    统计网格中岛屿的数量:图的遍历问题,可以使用DFS和BFS,其中,为了避免重复遍历问题,定义visited数组记录遍历过的位置,遍历过将该位置赋为1,没有遍历过为0;
    循环遍历grid,当该点为1且visited中对应点为0时,岛屿数量加1,同时进入DFS或BFS,把相通的点都遍历到,visited对应位置修改为1;
    */
    int numIslands(vector<vector<char>>& grid) {
    
    
        if(grid.size()==0 || grid[0].size()==0) return 0;
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> visited(m, vector<int>(n));
        for(int i=0; i<m; i++){
    
    
            for(int j=0; j<n; j++){
    
    
                visited[i][j] = 0;
            }
        }
        int num = 0;
        for(int i=0; i<m; i++){
    
    
            for(int j=0; j<n; j++){
    
    
                if(grid[i][j]=='1' && visited[i][j]==0){
    
    
                    num++;
                    DFS(grid, visited, i, j);
                }
            }
        }
        return num;
    }
};


class Solution {
    
    
public:
    /*
    广度遍历grid:
    1. 定义坐标偏移量dx,dy,在遍历过程中,使用x+dx,y+dy来定义四个方向的相邻位置;
    2. 定义队列存放访问到的grid为1的x,y值,将初始的x,y入队列,同时将visited[x][y]赋为1;
    3. 当队列不为空时,循环遍历队列:
    3.1 取出队头的x,y,循环遍历4个方向的相邻元素,如果该相邻点为1且visited中对应点为0时,将该相邻点位置入队列,同时将visited[new_x][new_y]赋为1;
    */
    void BFS(vector<vector<char>>& grid, vector<vector<int>> &visited, int x, int y){
    
    
        vector<int> dx = {
    
    0, 0, -1, 1};
        vector<int> dy = {
    
    -1, 1, 0, 0};
        visited[x][y] = 1;
        queue<pair<int, int>> island;
        island.push(make_pair(x, y));
        while(!island.empty()){
    
    
            int old_x = island.front().first;
            int old_y = island.front().second;
            island.pop();
            for(int i=0; i<4; i++){
    
    
                int new_x = old_x + dx[i];
                int new_y = old_y + dy[i];
                if(new_x >= 0 && new_x < grid.size() && new_y >= 0 && new_y < grid[0].size()){
    
    
                    if(grid[new_x][new_y]=='1' && visited[new_x][new_y]==0){
    
    
                        island.push(make_pair(new_x, new_y));
                        visited[new_x][new_y] = 1;
                    }
                }
            }
        }
    }

    /*
    统计网格中岛屿的数量:图的遍历问题,可以使用DFS和BFS,其中,为了避免重复遍历问题,定义visited数组记录遍历过的位置,遍历过将该位置赋为1,没有遍历过为0;
    循环遍历grid,当该点为1且visited中对应点为0时,岛屿数量加1,同时进入DFS或BFS,把相通的点都遍历到,visited对应位置修改为1;
    */
    int numIslands(vector<vector<char>>& grid) {
    
    
        if(grid.size()==0 || grid[0].size()==0) return 0;
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> visited(m, vector<int>(n));
        for(int i=0; i<m; i++){
    
    
            for(int j=0; j<n; j++){
    
    
                visited[i][j] = 0;
            }
        }
        int num = 0;
        for(int i=0; i<m; i++){
    
    
            for(int j=0; j<n; j++){
    
    
                if(grid[i][j]=='1' && visited[i][j]==0){
    
    
                    num++;
                    BFS(grid, visited, i, j);
                }
            }
        }
        return num;
    }
};

Guess you like

Origin blog.csdn.net/weixin_43273742/article/details/107740799