0515(每日一题简单题?)

695

/*
 * 给你一个大小为 m x n 的二进制矩阵 grid 。
岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
岛屿的面积是岛上值为 1 的单元格的数目。
计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。
思路:
1.先判断是否超出边界,若超出边界就直接返回0,否则检查该方块是否是陆地,若是陆地,就将该陆地标记为水面,返回时加1
 2.对每个节点进行遍历(两层for循环)
 */
class Solution {
private:
    int Max = 0;

    int dfs(int i, int j, vector <vector<int>> &grid) {
        if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || grid[i][j] == 0)return 0;
        grid[i][j] = 0;
        return 1 + dfs(i - 1, j, grid)
               + dfs(i + 1, j, grid)
               + dfs(i, j - 1, grid)
               + dfs(i, j + 1, grid);
    }

public:
    int maxAreaOfIsland(vector <vector<int>> &grid) {
//        vector <vector<int>> vis(grid.size(), vector<int>(grid[0].size()));
        for (int i = 0; i < grid.size(); i++) {
            for (int j = 0; j < grid[0].size(); j++) {
                if (grid[i][j] == 1)
                    Max = max(dfs(i, j, grid), Max);
            }
        }
        return Max;
    }
};

812 每日一题,简单题?

/*给定包含多个点的集合,从其中取三个点组成三角形,返回能组成的最大三角形的面积。
 *
 * */
class Solution {
private:
    int cross(const vector<int> & p, const vector<int> & q, const vector<int> & r) {
        return (q[0] - p[0]) * (r[1] - q[1]) - (q[1] - p[1]) * (r[0] - q[0]);
    }

    vector<vector<int>> getConvexHull(vector<vector<int>>& points) {
        int n = points.size();
        if (n < 4) {
            return points;
        }
        /* 按照 x 大小进行排序,如果 x 相同,则按照 y 的大小进行排序 */
        sort(points.begin(), points.end(), [](const vector<int> & a, const vector<int> & b) {
            if (a[0] == b[0]) {
                return a[1] < b[1];
            }
            return a[0] < b[0];
        });
        vector<vector<int>> hull;
        /* 求出凸包的下半部分 */
        for (int i = 0; i < n; i++) {
            while (hull.size() > 1 && cross(hull[hull.size() - 2], hull.back(), points[i]) <= 0) {
                hull.pop_back();
            }
            hull.emplace_back(points[i]);
        }
        int m = hull.size();
        /* 求出凸包的上半部分 */
        for (int i = n - 2; i >= 0; i--) {
            while (hull.size() > m && cross(hull[hull.size() - 2], hull.back(), points[i]) <= 0) {
                hull.pop_back();
            }
            hull.emplace_back(points[i]);
        }
        /* hull[0] 同时参与凸包的上半部分检测,因此需去掉重复的 hull[0] */
        hull.pop_back();
        return hull;
    }

    double triangleArea(int x1, int y1, int x2, int y2, int x3, int y3) {
        return 0.5 * abs(x1 * y2 + x2 * y3 + x3 * y1 - x1 * y3 - x2 * y1 - x3 * y2);
    }

public:
    double largestTriangleArea(vector<vector<int>> & points) {
        auto convexHull = getConvexHull(points);
        int n = convexHull.size();
        double ret = 0.0;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1, k = i + 2; j + 1 < n; j++) {
                while (k + 1 < n) {
                    double curArea = triangleArea(convexHull[i][0], convexHull[i][1], convexHull[j][0], convexHull[j][1], convexHull[k][0], convexHull[k][1]);
                    double nextArea = triangleArea(convexHull[i][0], convexHull[i][1], convexHull[j][0], convexHull[j][1], convexHull[k + 1][0], convexHull[k + 1][1]);
                    if (curArea >= nextArea) {
                        break;
                    }
                    k++;
                }
                double area = triangleArea(convexHull[i][0], convexHull[i][1], convexHull[j][0], convexHull[j][1], convexHull[k][0], convexHull[k][1]);
                ret = max(ret, area);
            }
        }
        return ret;
    }
};

offer13

/*
 * 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
 *
 * */
class Solution {
private:
    //计算数字个数之和
    int digi_sum(int A) {
        int sum = 0;
        while (A > 0) {
            sum += A % 10;
            A /= 10;
        }
        return sum;
    }

    //利用二维数组保存访问数据
    int dfs(int i, int j, int n, int m, int k, vector <vector<bool>> &vis) {
        //若出界(i<0||j<0||i>=m||j>=n),或者是数位和大于K(digi_sum(i)+digi_sum(j))>k或者是访问过vis[i][j]==true,就返回0
        if (i < 0 || j < 0 || i >= m || j >= n || (digi_sum(i) + digi_sum(j)) > k || vis[i][j] == true)return 0;
        //没访问过(i,j)就标记vis[i][j]==true
        vis[i][j] = true;
        //因为新增加访问,就可以在结果上+1,递归的访问上下左右
        return 1 + dfs(i - 1, j, n, m, k, vis)
               + dfs(i + 1, j, n, m, k, vis)
               + dfs(i, j - 1, n, m, k, vis)
               + dfs(i, j + 1, n, m, k, vis);
    }

public:
    int movingCount(int m, int n, int k) {
        vector <vector<bool>> vis(m, vector<bool>(n));
        //递归从零开始
        int ans = dfs(0, 0, n, m, k, vis);
        return ans;
    }
};



offer26

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 * 输入两棵二叉树A和B,判断B是不是A的子结构。(约定空树不是任意一个树的子结构)

B是A的子结构, 即 A中有出现和B相同的结构和节点值。

例如:
给定的树 A:

     3
    / \
   4   5
  / \
 1   2
给定的树 B:

   4 
  /
 1
返回 true,因为 B 与 A 的一个子树拥有相同的结构和节点值。

*判断B是否为另一颗树A的子结构
* 思路:最直观的想法就是遍历A树的所有节点,并以该节点为起点与B树进行对比:
* 对比过程:
* 1.若B扫描到的节点为空则说明经过之前的若干次检查(递归),直到找到空节点都不能找到不同的节点,则说明B是A的子结构
* 2.若B不为空,if(rt1==nullptr||rt1->val!=rt2->val),则若A为空则说明肯定不是子结构
*
*
* */
class Solution {
private:
    bool find(TreeNode *rt1, TreeNode *rt2) {
        if (rt2 == nullptr)return true;
        if (rt1 == nullptr || rt1->val != rt2->val)return false;
        return find(rt1->left, rt1->left) && find(rt1->right, rt2->right);
    }

public:
    bool isSubStructure(TreeNode *A, TreeNode *B) {
        return (A != nullptr && B != nullptr) &&
               (find(A, B) || isSubStructure(A->left, B) || isSubStructure(A->right, B));
        //先进行非空检查,再进行以两树根节点为起点的检查,再递归地以A树子节点和B树根节点为参数的检查
    }
};

posted @ 2022-05-16 00:06  ftwftw  阅读(40)  评论(0)    收藏  举报