第一周训练题解

104. 二叉树的最大深度

https://leetcode.cn/problems/maximum-depth-of-binary-tree/

思路:可以用递归的思路,从上往下执行。对于每个节点,若左右子节点都为空,则该节点为根的子树最大深度为1。若左右子节点不为空,则该节点为根的子树最大深度为左右子节点为子树最大深度较大的再加1。

代码:

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (root == NULL) return 0 ;
        int res = 1 ;
        if (root->left != NULL) {
            int r = maxDepth(root->left) ;
            if (r + 1 > res) res = r + 1 ;
        }
        if (root->right != NULL) {
            int r = maxDepth(root->right) ;
            if (r + 1 > res) res = r + 1 ;
        }
        // cout << root->val << "  " << res << endl ;
        return res ;
    }
};

101. 对称二叉树

https://leetcode.cn/problems/symmetric-tree/

思路:如果二叉树是对称的,那么先序遍历喝后续遍历应该是一样的。过程中间,对空节点用-1来代替,防止部分情况下不同的两棵树,先序遍历却相同的情况。

vector<int> rr ;
vector<int> ll ;

void dfsl(TreeNode* root) {
    if (root == NULL) {
        ll.push_back(-1) ;
        return ;
    }
    dfsl(root->left) ;
    dfsl(root->right) ;
    ll.push_back(root->val) ;
}

void dfsr(TreeNode* root) {
    if (root == NULL) {
        rr.push_back(-1) ;
        return ;
    }
    dfsr(root->right) ;
    dfsr(root->left) ;
    rr.push_back(root->val) ;
}


class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        rr.clear() ;
        ll.clear() ;
        dfsl(root) ;
        dfsr(root) ;
        for (int i = 0 ; i < ll.size() ; ++i) {
            cout << ll[i] << " " << rr[i] << endl ;
            if (ll[i] != rr[i]) {
                return false ;
            }
        }

        
        return true ;
    }
};

111. 二叉树的最小深度

https://leetcode.cn/problems/minimum-depth-of-binary-tree/

思路:可以用递归的思路,从上往下执行。对于每个节点,若左右子节点都为空,则该节点为根的子树最小深度为1。若左右子节点不为空,则该节点为根的子树最小深度为左右子节点为子树最小深度较小的再加1。

代码:

class Solution {
public:
    int minDepth(TreeNode* root) {
        if (root == NULL) return 0 ;
        if (root->left == NULL && root->right == NULL) {
            return 1 ;
        }
        int res = 1e5 ;
        if (root->left != NULL) {
            res = min(minDepth(root->left) + 1 , res) ;
        }
        if (root->right != NULL) {
            res = min(minDepth(root->right) + 1 , res) ;
        }
        return res ;
    }
};

733. 图像渲染

https://leetcode.cn/problems/flood-fill/

思路:

记录初始点的值,从初始点向四周搜索,若搜到的点颜色与初始点的值相同,进行染色。

代码:

int vis[100][100] ;
class Solution {
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {
        memset(vis , 0 , sizeof(vis)) ; 
        queue<int>x, y ;
        x.push(sr) ;
        y.push(sc) ;
        int dirx[] = {0 , 1 , 0 , -1} ;
        int diry[] = {1 , 0 , -1 , 0} ;
        int oldcolor = image[sr][sc] ;
        vis[sr][sc] = 1 ;
        while (!x.empty()) {
            int nowx = x.front() ;
            x.pop() ;
            int nowy = y.front() ;
            y.pop() ;
            image[nowx][nowy] = color ;
            for (int i = 0 ; i < 4 ; ++i) {
                int nx = nowx + dirx[i] ;
                int ny = nowy + diry[i] ;
                if (nx < 0) continue ;
                if (ny < 0) continue ;
                if (nx >= image.size()) continue ;
                if (ny >= image[0].size()) continue ;

                if (vis[nx][ny] == 1) continue ;
                vis[nx][ny] = 1 ;
                if (image[nx][ny] == oldcolor) {
                    x.push(nx) ;
                    y.push(ny) ;
                }
            }
        }
        return image ;
    }
};

690. 员工的重要性

https://leetcode.cn/problems/employee-importance/description/

思路:象遍历树一样,从头节点往下搜,然后逐个累加重要度。

代码:

int id2index[2005] ;
class Solution {
public:
    int getImportance(vector<Employee*> employees, int id) {
        for (int i = 0 ; i < employees.size() ; ++i) {
            id2index[employees[i]->id] = i ;
        }
        queue<int> Q ;
        Q.push(id) ;
        int res = 0 ;
        while (!Q.empty()) {
            int now = Q.front() ;
            Q.pop() ;
            int index = id2index[now] ;
            res += employees[index]->importance ;
            for (int i = 0 ; i < employees[index]->subordinates.size() ; ++i) {
                Q.push(employees[index]->subordinates[i]) ;
            }
        }
        return res ;
    }
};

841. 钥匙和房间

https://leetcode.cn/problems/keys-and-rooms/

思路:按照搜索思路,逐个打开可以打开的房间,过程中统计打开了多少房间,与总房间数比对

代码:

int vis[1005] ;
class Solution {
public:
    bool canVisitAllRooms(vector<vector<int>>& rooms) {
        memset(vis , 0 , sizeof(vis)) ;
        queue<int>Q ;
        Q.push(0) ;
        int cnt = 1 ;
        vis[0] = 1 ;
        while (!Q.empty()) {
            int now = Q.front() ;
            Q.pop() ;
            for (int i = 0 ; i < rooms[now].size() ; ++i) {
                int nx = rooms[now][i] ;
                if (vis[nx] == 0) {
                    Q.push(nx) ;
                    ++cnt ;
                }
                vis[nx] = 1 ;
            }
        }
        if (cnt == rooms.size()) {
            return true ;
        }
        return false ;
    }
};

130. 被围绕的区域

https://leetcode.cn/problems/surrounded-regions/

思路:暴力,因为地图比较小,100步就可以往里渗透

代码:

int vis[205][205] ;
class Solution {
public:
    void solve(vector<vector<char>>& board) {
        memset(vis , 0 , sizeof(vis)) ;
        int n = board.size() ;
        int m = board[0].size() ;

        for (int time = 0 ; time < 100 + 5 ; ++time) {
            for (int i = 0 ; i < n ; ++i) {
                for (int j = 0 ; j < m ; ++j) {
                    if (board[i][j] == 'X') continue ;
                    if (i == 0 || j == 0 || i == n - 1 || j == m - 1) {
                        vis[i][j] = 1 ;
                        continue ;
                    }
                    if (vis[i - 1][j]) vis[i][j] = 1 ;
                    if (vis[i + 1][j]) vis[i][j] = 1 ;
                    if (vis[i][j + 1]) vis[i][j] = 1 ;
                    if (vis[i][j - 1]) vis[i][j] = 1 ;
                }
            }
        }
        for (int i = 0 ; i < n ; ++i) {
            for (int j = 0 ; j < m ; ++j) {
                if (!vis[i][j]) {
                    if(board[i][j] == 'O') {
                        board[i][j] = 'X' ;
                    }
                }
            }
        }
        return ;
    }
};

113. 路径总和 II

https://leetcode.cn/problems/path-sum-ii/

思路:DFS搜索,到每个叶子节点判断是否符合题目要求。

代码:

vector<int>V ;
vector<vector<int>> res ;
int sum = 0 ;
int aim = 0 ;
void DFS(TreeNode* now) {
    if (now == NULL) return ;
    sum += now->val ;
    V.push_back(now->val) ;
    if (now->left != NULL) {
        DFS(now->left) ;
    }
    if (now->right != NULL) {
        DFS(now->right) ;
    }

    if (now->right == NULL && now->left == NULL) {
        if (sum == aim) {
            res.push_back(V) ;
        }
    }
    sum -= now->val ;
    V.pop_back() ;
}

class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        aim = targetSum ;
        V.clear() ;
        res.clear() ;
        DFS(root) ;
        return res ;
    }
};

542. 01 矩阵

https://leetcode.cn/problems/01-matrix/

思路:有点BFS的思路,从0点逐步向外搜索。

代码:

class Solution {
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& mat) {
        map<pair<int,int>,int> M ;
        cout << M[make_pair(1 , 1)] << endl ;
        int n = mat.size() ;
        int m = mat[0].size() ;
        queue<pair<int,int>> Q ;
        for (int i = 0 ; i < n ; ++i) {
            for (int j = 0 ; j < m ; ++j) {
                if (mat[i][j] == 0) {
                    Q.push(make_pair(i , j)) ;
                    M[make_pair(i , j)] = 1 ;
                }
            }
        }
        int dirx[] = {0 , 1 , 0 , -1} ;
        int diry[] = {1 , 0 , -1 , 0} ;
        while(!Q.empty()) {
            int nowx = Q.front().first ;
            int nowy = Q.front().second ;
            Q.pop() ;
            for (int i = 0 ; i < 4 ; ++i) {
                int nexx = nowx + dirx[i] ;
                int nexy = nowy + diry[i] ;
                
                if (nexx < 0 || nexy < 0 || nexx == n || nexy == m) {
                    continue ;
                }
                if (M[make_pair(nexx , nexy)] == 1) continue ;
                
                mat[nexx][nexy] = mat[nowx][nowy] + 1 ;
                Q.push(make_pair(nexx , nexy)) ;
                M[make_pair(nexx , nexy)] = 1 ;
            }
            
        }
        return mat ;
    }
};

417. 太平洋大西洋水流问题


https://leetcode.cn/problems/pacific-atlantic-water-flow/

思路:搞两次BFS,一次用来统计能到左上角的方块,一次用来统计能到右下角的方块。

代码:

struct Node {
    int x ;
    int y ;
};

class Solution {
public:
    vector<vector<int>> pacificAtlantic(vector<vector<int>>& heights) {
        int n = heights.size() ;
        int m = heights[0].size() ;
        int dirx[] = {0 , 1 , 0 , -1} ;
        int diry[] = {1 , 0 , -1 , 0} ;
        vector<vector<int>> vis ;
        vis = vector(n , vector(m , 0)) ;
        vector<vector<int>> res1(n , vector(m , 0)) ;
        vector<vector<int>> res2(n , vector(m , 0)) ;
        queue<Node> Q ;
        Node now ;

        for (int i = 0 ; i < n ; ++i) {
            now.x = i ;
            now.y = 0 ;
            Q.push(now) ;
            res1[i][0] = 1 ;
        }
        for (int i = 0 ; i < m ; ++i) {
            now.x = 0 ;
            now.y = i ;
            Q.push(now) ;
            res1[0][i] = 1 ;
        }

        while (!Q.empty()) {
            now = Q.front() ;
            Q.pop() ;
            int nowx = now.x ;
            int nowy = now.y ;
            for (int i = 0 ; i < 4 ; ++i) {
                int newx = nowx + dirx[i] ;
                int newy = nowy + diry[i] ;
                if (newx < 0 || newy < 0 || newx == n || newy == m) continue ;
                if (vis[newx][newy]) continue ;
                if (heights[newx][newy] >= heights[nowx][nowy]) {
                    now.x = newx ;
                    now.y = newy ;
                    Q.push(now) ;
                    vis[newx][newy] = 1;
                    res1[newx][newy] = 1 ;
                }
            }
        }

        vis = vector(n , vector(m , 0)) ;
        for (int i = 0 ; i < n ; ++i) {
            now.x = i ;
            now.y = m - 1 ;
            Q.push(now) ;
            res2[i][m - 1] = 1 ;
        }
        for (int i = 0 ; i < m ; ++i) {
            now.x = n - 1 ;
            now.y = i ;
            Q.push(now) ;
            res2[n - 1][i] = 1 ;
        }

        while (!Q.empty()) {
            now = Q.front() ;
            Q.pop() ;
            int nowx = now.x ;
            int nowy = now.y ;
            for (int i = 0 ; i < 4 ; ++i) {
                int newx = nowx + dirx[i] ;
                int newy = nowy + diry[i] ;
                if (newx < 0 || newy < 0 || newx == n || newy == m) continue ;
                if (vis[newx][newy]) continue ;
                if (heights[newx][newy] >= heights[nowx][nowy]) {
                    now.x = newx ;
                    now.y = newy ;
                    Q.push(now) ;
                    vis[newx][newy] = 1;
                    res2[newx][newy] = 1 ;
                }
            }
        }
        vector<vector<int>> res ;
        vector<int> res_tmp ;
        res_tmp.push_back(0) ;
        res_tmp.push_back(0) ;
        for (int i = 0 ; i < n ; ++i) {
            for (int j = 0 ; j < m ; ++j) {
                if (res1[i][j] && res2[i][j]) {
                    res_tmp[0] = i ;
                    res_tmp[1] = j ;
                    res.push_back(res_tmp) ;
                }
            }
        }
        return res ;
    }
};

473. 火柴拼正方形

https://leetcode.cn/problems/matchsticks-to-square/

思路:好像只能去搜索。相当于四个桶往里面放东西。然后从大的优先开始放。因为只有15个火柴,所以搜索量不会特别大。

代码:

int sum[4] ;

bool solve(vector<int>& matchsticks , int id , int u) {
    
    if (id == matchsticks.size()) {
        return true ;
    }
    for (int i = 0 ; i < 4 ; ++i) {
        if (sum[i] + matchsticks[id] > u) {
            continue ;
        }
        else {
            sum[i] += matchsticks[id] ;
            if (solve(matchsticks , id + 1 , u)) {
                return true ;
            }
            sum[i] -= matchsticks[id] ;
        }
    }
    return false ;
}

int cmp (int a , int b) {
    return a > b ;
}

class Solution {
public:
    bool makesquare(vector<int>& matchsticks) {
        int s = 0 ;
        for (int i = 0 ; i < 4 ; ++i) {
            sum[i] = 0 ;
        }
        for (int i = 0 ; i < matchsticks.size() ; ++i) {
            s += matchsticks[i] ;
        }
        if (s % 4 != 0) return false ;
        cout << "yes!" << endl ;
        sort(matchsticks.begin() , matchsticks.end() , cmp) ;
        return solve(matchsticks , 0 , s / 4) ;
        
    }
};

773. 滑动谜题

https://leetcode.cn/problems/sliding-puzzle/description/

思路:因为只有六个方块,其实状态不是特别多,并且问题问的是最少通过多少次转移,就很像最短路。于是用字符串来保存状态,然后去求最短路。

代码:

unordered_map<string, int> vis ;
unordered_map<string, int> dist ;
vector<string> V ;
int dirx[] = {0 , 1 , 0 , -1} ;
int diry[] = {1 , 0 , -1 , 0} ;

void spfa(string sta) {
    vis[sta] = 1 ;
    dist[sta] = 0 ;
    queue<string> Q ;
    Q.push(sta) ;
    while (!Q.empty()) {
        string nowstr = Q.front() ;
        Q.pop() ;
        vis[nowstr] = 0 ;
        // 从数字还原二维数组
        V.clear() ;
        string s1 = nowstr.substr(0 , 3) ;
        string s2 = nowstr.substr(3) ;
        V.push_back(s1) ;
        V.push_back(s2) ;
        string kaka = V[0] + V[1] ;
        int nowx = 0 ;
        int nowy = 0  ;
        for (int i = 0 ; i < V.size() ; ++i) {
            for (int j = 0 ; j < 3 ; ++j) {
                if (V[i][j] == '0') {
                    nowx = i ;
                    nowy = j ;
                }
            }
        }
        for (int i = 0  ; i < 4 ; ++i) {
            int newx = dirx[i] + nowx ;
            int newy = diry[i] + nowy ;

            if (newx < 0 || newy < 0 || newx == 2 || newy == 3) {
                continue ;
            }

            kaka = V[0] + V[1] ;
            // 交换位置
            char yo ;
            yo = V[newx][newy] ;
            V[newx][newy] = V[nowx][nowy] ;
            V[nowx][nowy] = yo ;

            kaka = V[0] + V[1] ;

            // 记录
            string newstr = V[0] + V[1] ;
            
            // 没有插入过
            if (dist.find(newstr) == dist.end()) {
                dist[newstr] = dist[nowstr] + 1 ;
                Q.push(newstr) ;
                vis[newstr] = 1 ;
            }
            // 插入过
            else {
                if(dist[nowstr] + 1 < dist[newstr]) {
                    dist[newstr] = dist[nowstr] + 1 ;
                    if (vis[newstr] == 0) {
                        Q.push(newstr) ;
                        vis[newstr] = 1 ;
                    }
                }
            }
            // 再换回来
            yo = V[newx][newy] ;
            V[newx][newy] = V[nowx][nowy] ;
            V[nowx][nowy] = yo ;

            string kaka = V[0] + V[1] ;
        }
    }
}

class Solution {
public:
    int slidingPuzzle(vector<vector<int>>& board) {
        vis.clear() ;
        dist.clear() ;
        string yoho = "" ;
        for (int i = 0 ; i < board.size() ; ++i) {
            for (int j = 0 ; j < board[0].size() ; ++j) {
                yoho = yoho + char(board[i][j] + '0') ;
            }
        }
        spfa(yoho) ;
        if (dist.find("123450") == dist.end()) {
            return -1 ;
        }
        else {
            return dist["123450"] ;
        }
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值