leetcode解题思路分析(六十四)542 - 551 题

  1. 01矩阵
    给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。两个相邻元素间的距离为 1 。

采用动态规划得解

class Solution {
    
    
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
    
    
        int m = matrix.size(), n = matrix[0].size();
        // 初始化动态规划的数组,所有的距离值都设置为一个很大的数
        vector<vector<int>> dist(m, vector<int>(n, INT_MAX / 2));
        // 如果 (i, j) 的元素为 0,那么距离为 0
        for (int i = 0; i < m; ++i) {
    
    
            for (int j = 0; j < n; ++j) {
    
    
                if (matrix[i][j] == 0) {
    
    
                    dist[i][j] = 0;
                }
            }
        }
        // 只有 水平向左移动 和 竖直向上移动,注意动态规划的计算顺序
        for (int i = 0; i < m; ++i) {
    
    
            for (int j = 0; j < n; ++j) {
    
    
                if (i - 1 >= 0) {
    
    
                    dist[i][j] = min(dist[i][j], dist[i - 1][j] + 1);
                }
                if (j - 1 >= 0) {
    
    
                    dist[i][j] = min(dist[i][j], dist[i][j - 1] + 1);
                }
            }
        }
        // 只有 水平向右移动 和 竖直向下移动,注意动态规划的计算顺序
        for (int i = m - 1; i >= 0; --i) {
    
    
            for (int j = n - 1; j >= 0; --j) {
    
    
                if (i + 1 < m) {
    
    
                    dist[i][j] = min(dist[i][j], dist[i + 1][j] + 1);
                }
                if (j + 1 < n) {
    
    
                    dist[i][j] = min(dist[i][j], dist[i][j + 1] + 1);
                }
            }
        }
        return dist;
    }
};


  1. 二叉树的直径
    给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

深度优先遍历一遍即可

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    
    
    int ans;
    int depth(TreeNode* rt){
    
    
        if (rt == NULL) {
    
    
            return 0; // 访问到空节点了,返回0
        }
        int L = depth(rt->left); // 左儿子为根的子树的深度
        int R = depth(rt->right); // 右儿子为根的子树的深度
        ans = max(ans, L + R + 1); // 计算d_node即L+R+1 并更新ans
        return max(L, R) + 1; // 返回该节点为根的子树的深度
    }
public:
    int diameterOfBinaryTree(TreeNode* root) {
    
    
        ans = 1;
        depth(root);
        return ans - 1;
    }
};


  1. 移除盒子
    给出一些不同颜色的盒子,盒子的颜色由数字表示,即不同的数字表示不同的颜色。你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续 k 个盒子(k >= 1),这样一轮之后你将得到 k * k 个积分。当你将所有盒子都去掉之后,求你能获得的最大积分和。

此题可用动态规划求解。以dp[l][r][k]表示从l到r的区间,以及r之后还有k个相同元素时最大积分和。之所以需要如此,是因为这个分数并不只依赖于子序列,也依赖于之前的移动对当前数组的影响,这可能让最终的子序列不是一个连续的子串

class Solution {
    
    
public:
    int dp[100][100][100];

    int removeBoxes(vector<int>& boxes) {
    
    
        memset(dp, 0, sizeof dp);
        return calculatePoints(boxes, 0, boxes.size() - 1, 0);
    }

    int calculatePoints(vector<int>& boxes, int l, int r, int k) {
    
    
        if (l > r) {
    
    
            return 0;
        }
        if (dp[l][r][k] == 0) {
    
    
            dp[l][r][k] = calculatePoints(boxes, l, r - 1, 0) + (k + 1) * (k + 1);
            for (int i = l; i < r; i++) {
    
    
                if (boxes[i] == boxes[r]) {
    
    
                    dp[l][r][k] = max(dp[l][r][k], calculatePoints(boxes, l, i, k + 1) + calculatePoints(boxes, i + 1, r - 1, 0));
                }
            }
        }
        return dp[l][r][k];
    }
};

  1. 省份数量

采取DFS/BFS遍历即可

class Solution {
    
    
public:
    void dfs(vector<vector<int>>& isConnected, vector<int>& visited, int provinces, int i) {
    
    
        for (int j = 0; j < provinces; j++) {
    
    
            if (isConnected[i][j] == 1 && !visited[j]) {
    
    
                visited[j] = 1;
                dfs(isConnected, visited, provinces, j);
            }
        }
    }

    int findCircleNum(vector<vector<int>>& isConnected) {
    
    
        int provinces = isConnected.size();
        vector<int> visited(provinces);
        int circles = 0;
        for (int i = 0; i < provinces; i++) {
    
    
            if (!visited[i]) {
    
    
                dfs(isConnected, visited, provinces, i);
                circles++;
            }
        }
        return circles;
    }
};


  1. 学生出勤记录
    如果一个学生的出勤记录中不超过一个’A’(缺勤)并且不超过两个连续的’L’(迟到),那么这个学生会被奖赏。
    你需要根据这个学生的出勤记录判断他是否会被奖赏。

遍历一遍判断即可

class Solution {
    
    
public:
    bool checkRecord(string s) 
    {
    
    
        int absent = 0, lateContinue = 0;

        for (auto c : s)
        {
    
    
            if (c == 'A')
            {
    
    
                lateContinue = 0;
                absent++;
                if (absent > 1) return false;
            }
            else if (c == 'L')
            {
    
    
                lateContinue++;
                if (lateContinue > 2) 
                    return false;
            }
            else
            {
    
    
                lateContinue = 0;
            }
        }

        return true;
    }
};

猜你喜欢

转载自blog.csdn.net/u013354486/article/details/113782100