ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2022-01-27每日刷题打卡

2022-01-27 16:03:01  阅读:162  来源: 互联网

标签:27 TreeNode int 01 right que 打卡 节点 left


2022-01-27每日刷题打卡

飞书——每日一题

面试题 17.21. 直方图的水量

给定一个直方图(也称柱状图),假设有人从上面源源不断地倒水,最后直方图能存多少水量?直方图的宽度为 1。

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的直方图,在这种情况下,可以接 6 个单位的水(蓝色部分表示水)。 感谢 Marcos 贡献此图。

示例:

rainwatertrap.png (412×161) (leetcode-cn.com)

输入: [0,1,0,2,1,0,1,3,2,1,2,1]
输出: 6

这题和42. 接雨水一样的写法,首先我们知道,只有中间的高度小于左右两边的高度才可以接到雨水,这种情况下我们可以使用头尾双指针向中间移动遍历。准备两个值l_max和r_max,来存左右两边的最大高度。开始遍历,每次比较height[l]和heigh[r]的大小,如果l大那就可以知道左边已经出现了大于当前高度的地方,只要在右边找到大于当前高度的地方即可,我们先更新一下最大高度,看是r_max大还是height[r]大,如果height[r]大就更新一下r_max,我们计算r_max-heigh[r]的值即为我们可以接到雨水的值,如果当前我们遍历到的柱子就是最高的柱子,那自然右边不会出现更高的柱子来让我们接雨水,所以是0,如果r_max大于heigh[r]则说明右边也有高的柱子,满足了中间小两边大的条件,此时能接雨水的容量就是r_max-heigh[r],然后r–。如果是l小了则以上操作改一下即可。

class Solution {
public:
    int trap(vector<int>& height) {
        int n=height.size();
        int i=0,j=n-1,ans=0,left=0,right=0;
        while(i<j)
        {
            if(height[i]<height[j])
            {
                left=max(left,height[i]);
                ans+=left-height[i];
                i++;
            }
            else
            {
                right=max(right,height[j]);
                ans+=right-height[j];
                j--;
            }
        }
        return ans;
    }
};

2047. 句子中的有效单词数

句子仅由小写字母(‘a’ 到 ‘z’)、数字(‘0’ 到 ‘9’)、连字符(’-’)、标点符号(’!’、’.’ 和 ‘,’)以及空格(’ ')组成。每个句子可以根据空格分解成 一个或者多个 token ,这些 token 之间由一个或者多个空格 ’ ’ 分隔。

如果一个 token 同时满足下述条件,则认为这个 token 是一个有效单词:

仅由小写字母、连字符和/或标点(不含数字)。
至多一个 连字符 ‘-’ 。如果存在,连字符两侧应当都存在小写字母(“a-b” 是一个有效单词,但 “-ab” 和 “ab-” 不是有效单词)。
至多一个 标点符号。如果存在,标点符号应当位于 token 的 末尾 。
这里给出几个有效单词的例子:“a-b.”、“afad”、“ba-c”、“a!” 和 “!” 。

给你一个字符串 sentence ,请你找出并返回 sentence 中 有效单词的数目 。

示例 1:

输入:sentence = “cat and dog”
输出:3
解释:句子中的有效单词是 “cat”、“and” 和 “dog”

这题真的太坑了!一个简单题wa了四次草。

准备一个计数器res=0,遍历sentence,遍历到的字符为空格就跳过,如果不是空格就开始一系列判断,先准备一个ans=1,当该单词不合格时,ans=0,如果合格了,当这个单词结束后把ans加到res上。在准备一个a=0,这个是计算‘-’字符的出现次数。开始判断,如果是数字,说明这已经不是一个合格的单词了,ans=0;如果是‘-’字符,则判断这个这个字符前后是否是字母,如果不是或者超过数组字符串长度了,说明这单词也不合格,ans=0,如果合格了,则a++,计算一次出现次数,下一次如果又遇到了‘-‘字符则说明也是一个不合格的单词;如果是’.'或’,‘或’!‘,则只能出现在末尾,即判断它的下一个字符是否是空格,或者是否是字符串的最后一个字符,如果是就是一个合格的单词,反之不是,ans=0。

等这些判断结束后,把ans加到res上。当遍历结束后,返回res。

class Solution {
public:
    int countValidWords(string sentence) {
        int n=sentence.size(),res=0;
        for(int i=0;i<n;i++)
        {
            if(sentence[i]!=' ')
            {
                int ans=1;
                int a=0;
                bool flag=true;
                while(i<n&&sentence[i]!=' ')
                {
                    if(!flag)i++;
                    else if(sentence[i]=='-')
                    {
                        if(i+1>=n||i-1<0||!islower(sentence[i-1])||!islower(sentence[i+1]))
                        {
                            ans=0;
                        }
                        else if(a>=1)
                        {
                            ans=0;
                        }
                        else
                        {
                            a++;
                        }
                        i++;
                    }
                    else if(sentence[i]=='.'||sentence[i]=='!'||sentence[i]==',')
                    {
                        if(i+1<n&&sentence[i+1]!=' ')
                            ans=0;
                        i++;
                    }
                    else if(sentence[i]>='0'&&sentence[i]<='9')
                    {
                        ans=0;
                        i++;
                    }
                    else i++;
                }
                i--;
                res+=ans;
            }
        }
        return res;
    }
};

1020. 飞地的数量

给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。

一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。

返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。

示例 1:

enclaves1.jpg (333×333) (leetcode.com)

输入:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
输出:3
解释:有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。

先遍历最外层,用广度搜索把遍历到的数值为1的块和与其相连的块变为0。然后再遍历一遍矩阵,计算有多少个0号地块。

class Solution {
public:
    typedef pair<int,int>PII;
    int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    int n,m;
    PII que[300000];
    int numEnclaves(vector<vector<int>>& grid) {
        n=grid.size(),m=grid[0].size();
        for(int i=0;i<n;i++)
        {
            if(grid[i][0]==1)
                bfs(grid,i,0,1,0);
            if(grid[i][m-1]==1)
                bfs(grid,i,m-1,1,0);
        }
        for(int i=0;i<m;i++)
        {
            if(grid[0][i]==1)
                bfs(grid,0,i,1,0);
            if(grid[n-1][i]==1)
                bfs(grid,n-1,i,1,0);
        }
        int ans=0;
        for(int i=1;i<n;i++)
            for(int j=1;j<m;j++)
                if(grid[i][j]==1)
                {
                    ans++;
                }
        return ans;
    }
    void bfs(vector<vector<int>>& grid,int x,int y,int s,int c)
    {
        que[0]={x,y};
        grid[x][y]=c;
        int hh=0,tt=0;
        while(hh<=tt)
        {
            auto t=que[hh++];
            for(int i=0;i<4;i++)
            {
                int a=t.first+dx[i],b=t.second+dy[i];
                if(a>=0&&a<n&&b>=0&&b<m&&grid[a][b]==s)
                {
                    grid[a][b]=c;
                    que[++tt]={a,b};
                }
            }
        }
    }
};

1161. 最大层内元素和

给你一个二叉树的根节点 root。设根节点位于二叉树的第 1 层,而根节点的子节点位于第 2 层,依此类推。

请返回层内元素之和 最大 的那几层(可能只有一层)的层号,并返回其中 最小 的那个。

示例 1:

capture.jpeg (332×291) (leetcode-cn.com)

输入:root = [1,7,0,7,-8,null,null]
输出:2
解释:
第 1 层各元素之和为 1,
第 2 层各元素之和为 7 + 0 = 7,
第 3 层各元素之和为 7 + -8 = -1,
所以我们返回第 2 层的层号,它的层内元素之和最大。

广度遍历获取每一层的所有节点值并加在一起,在每一层遍历的过程中维护最大值,并记录最大值出现的层数。遍历全部结束后返回记录的层数。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int maxLevelSum(TreeNode* root) {
        queue<TreeNode*>que;
        que.push(root);
        int ans=INT_MIN,u=-1,deep=1;
        while(que.size())
        {
            int len=que.size();
            int sum=0;
            for(int i=0;i<len;i++)
            {
                sum+=que.front()->val;
                if(que.front()->left)que.push(que.front()->left);
                if(que.front()->right)que.push(que.front()->right);
                que.pop();
            }
            if(sum>ans)
            {
                ans=sum;
                u=deep;
            }
            deep++;
        }
        
        
        return u;
    }
};

1162. 地图分析

你现在手里有一份大小为 n x n 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的。如果网格上只有陆地或者海洋,请返回 -1。

我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1| 。

示例 1:

1336_ex1.jpeg (185×87) (leetcode-cn.com)

输入:grid = [[1,0,1],[0,0,0],[1,0,1]]
输出:2
解释:
海洋单元格 (1, 1) 和所有陆地单元格之间的距离都达到最大,最大距离为 2。

广度搜索,先找到所有的数值为1的地块,并以那些地块为起点同时开始广度搜索(但有些示例会有特殊情况,比如矩阵全部都是0或者都是1,这样的情况只能是返回-1,所以我们进行广度搜索前先判断一下,记录的起点数量是不是为0或者是不是等于矩阵的大小,如果是就直接返回-1),把遍历到的地块赋值为当前地块并+1。等广度遍历结束后,遍历一遍矩阵,找出其中的最大值,并返回这个最大值。

class Solution {
public:
    typedef pair<int,int>PII;
    PII que[10010];
    int maxDistance(vector<vector<int>>& grid) {
        int n=grid.size(),m=grid[0].size();
        int hh=0,tt=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                if(grid[i][j]==1)
                    que[tt++]={i,j};
        if(tt==0||tt==n*m)return -1;
        int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
        while(hh<=tt)
        {
            auto t=que[hh++];
            for(int i=0;i<4;i++)
            {
                int a=t.first+dx[i],b=t.second+dy[i];
                if(a>=0&&a<n&&b>=0&&b<m&&grid[a][b]==0)
                {
                    que[tt++]={a,b};
                    grid[a][b]=grid[t.first][t.second]+1;
                }
            }
        }
        int ans=0;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)   
                if(ans<grid[i][j])
                {
                    ans=grid[i][j];
                }
        return ans-1;
    }
};

1091. 二进制矩阵中的最短路径

给你一个 n x n 的二进制矩阵 grid 中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回 -1 。

二进制矩阵中的 畅通路径 是一条从 左上角 单元格(即,(0, 0))到 右下角 单元格(即,(n - 1, n - 1))的路径,该路径同时满足下述要求:

路径途经的所有单元格都的值都是 0 。
路径中所有相邻的单元格应当在 8 个方向之一 上连通(即,相邻两单元之间彼此不同且共享一条边或者一个角)。
畅通路径的长度 是该路径途经的单元格总数。

示例 1:

example1_1.png (1884×880) (leetcode.com)

输入:grid = [[0,1],[1,0]]
输出:2

走迷宫问题,以左上角为起点到达右下角,只不过方向从上下左右4个方向基础上又加上了左上,左下,右上和右下四个方向,一共八个方向,其它和正常的迷宫问题一样。注意的是,一开始要先判断一下,起点和终点的初始值是否是0,如果不是,返回-1。

class Solution {
public:
    typedef pair<int,int>PII;
    PII que[10010];
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        int n=grid.size(),m=grid[0].size();
        que[0]={0,0};
        if(n==1&&m==1&&grid[0][0]==0)return 1;
        if(grid[0][0]==1||grid[n-1][m-1]==1)return -1;
        grid[0][0]=1;
        int dx[8]={1,0,-1,0,1,1,-1,-1},dy[8]={0,1,0,-1,-1,1,-1,1};
        int hh=0,tt=0;
        grid[n-1][m-1]=-1;
        while(hh<=tt)
        {
            auto t=que[hh++];
            for(int i=0;i<8;i++)
            {
                int a=t.first+dx[i],b=t.second+dy[i];
                if(a>=0&&a<n&&b>=0&&b<m&&(grid[a][b]==0||grid[a][b]==-1))
                {
                    grid[a][b]=grid[t.first][t.second]+1;
                    que[++tt]={a,b};
                }
            }
        }
        return grid[n-1][m-1];
    }
};

1123. 最深叶节点的最近公共祖先

给你一个有根节点 root 的二叉树,返回它 最深的叶节点的最近公共祖先 。

回想一下:

叶节点 是二叉树中没有子节点的节点
树的根节点的 深度 为 0,如果某一节点的深度为 d,那它的子节点的深度就是 d+1
如果我们假定 A 是一组节点 S 的 最近公共祖先,S 中的每个节点都在以 A 为根节点的子树中,且 A 的深度达到此条件下可能的最大值。

示例 1:

sketch1.png (722×614) (s3-lc-upload.s3.amazonaws.com)

输入:root = [3,5,1,6,2,0,8,null,null,7,4]
输出:[2,7,4]
解释:我们返回值为 2 的节点,在图中用黄色标记。
在图中用蓝色标记的是树的最深的节点。
注意,节点 6、0 和 8 也是叶节点,但是它们的深度是 2 ,而节点 7 和 4 的深度是 3 。

这题和865. 具有所有最深节点的最小子树一样。

获取左右子树的高度,如果高度一样,说明当前节点就是最深节点的公共祖先了,返回当前节点。如果左子树的高度大于右子树,说明最深节点的公告祖先应当在左子树(右子树都不是最深节点,怎么可能在右子树),我们就去左子树找公告祖先,即重复开头的步骤,直到找到某个节点,它的左右子树相等为止,那个节点就是我们要的结果,返回它。如果是右子树高度大于左子树,则去右子树找。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* lcaDeepestLeaves(TreeNode* root) {
        if(!root)return root;
        int left=getDeep(root->left);
        int right=getDeep(root->right);
        if(left==right)return root;
        else if(left>right)return lcaDeepestLeaves(root->left);
        return lcaDeepestLeaves(root->right);
    }
    int getDeep(TreeNode* root)
    {
        if(!root)return 0;
        return 1+max(getDeep(root->left),getDeep(root->right));
    }
};

1302. 层数最深叶子节点的和

给你一棵二叉树的根节点 root ,请你返回 层数最深的叶子节点的和 。

示例 1:

1483_ex1.png (273×265) (leetcode-cn.com)

输入:root = [1,2,3,4,5,null,6,7,null,null,null,null,8]
输出:15

层序遍历(广度搜索)获得每一层的节点,并把节点值存入二维数组里,二维数组里每一层对应每一层的节点值。直接找到最后一层,把所有值加在一起,返回总和。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int deepestLeavesSum(TreeNode* root) {
        queue<TreeNode*>que;
        que.push(root);
        vector<vector<int>>v;
        while(que.size())
        {
            int len=que.size();
            vector<int>ans;
            for(int i=0;i<len;i++)
            {
                ans.push_back(que.front()->val);
                if(que.front()->left)que.push(que.front()->left);
                if(que.front()->right)que.push(que.front()->right);
                que.pop();
            }
            v.push_back(ans);
        }
        int n=v.size();
        int sum=0;
        for(auto i:v[n-1])sum+=i;
        return sum;
    }
};

标签:27,TreeNode,int,01,right,que,打卡,节点,left
来源: https://blog.csdn.net/fnmdpnmsl/article/details/122718966

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有