leetcode秋招冲刺(专题4--6)

专题4:矩阵

题目463:岛屿的周长(NO)

  • 解题思路:每个方块必定有四个边,直接判断每个方块不合法的边数然后减去就行了。

给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。

网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。

岛屿中没有"湖"("湖" 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。

cpp 复制代码
class Solution {
public:
    int islandPerimeter(vector<vector<int>>& grid) {
        //直接从侧面入手,查看哪些不能作为边长,靠着方块的就不能算边长
        int ans=0;
        for(int i=0;i<grid.size();i++)
        {
            for(int j=0;j<grid[i].size();j++)
            {
                if(grid[i][j]==1)
                {
                    //是岛屿,开始判断不合法的边
                    int count=4;//原来合法的边数

                    if(j>=1&&grid[i][j-1]==1)count--;//左边不合法
                    if(j<grid[i].size()-1&&grid[i][j+1]==1)count--;//右边不合法
                    if(i>=1&&grid[i-1][j]==1)count--;//上边不合法
                    if(i<grid.size()-1&&grid[i+1][j]==1)count--;//下边不合法

                    ans+=count;
                }
            }
        }

        return ans;
    }
};

题目566:重塑矩阵(NO)

  • 解题思路:先判断元素的个数是否不变,再使用vector构建二维数组的方法重新构建一个容器,后面通过将原来数组展开成一位数组进行for遍历,进行数据的填充。

在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。

给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。

如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。

cpp 复制代码
class Solution {
public:
    vector<vector<int>> matrixReshape(vector<vector<int>>& mat, int r, int c) {
        int previous_row=mat.size();
        int previous_col=mat[0].size();

        if(previous_row*previous_col!=r*c)
        {
            //元素个数不一样了,表示不能重塑,返回元素组
            return mat;
        }

        //重新构建一个r行c列的容器
        vector<vector<int>> ans(r,vector<int>(c));//记住这种写法

        for(int i=0;i<previous_row*previous_col;i++)
        {
            //这里主要是以列为主,填完一列到下一个
            ans[i/c][i%c]=mat[i/previous_col][i%previous_col];
        }
        return ans;
    }
};

题目661:图片平滑器(YES)

  • 这题我自己给出的不是很好,是强行判断周边的所有元素的状态。解析给出的也是用时四层for强行分析,值得借鉴

图像平滑器 是大小为 3 x 3 的过滤器,用于对图像的每个单元格平滑处理,平滑处理后单元格的值为该单元格的平均灰度。

每个单元格的 平均灰度 定义为:该单元格自身及其周围的 8 个单元格的平均值,结果需向下取整。(即,需要计算蓝色平滑器中 9 个单元格的平均值)。

如果一个单元格周围存在单元格缺失的情况,则计算平均灰度时不考虑缺失的单元格(即,需要计算红色平滑器中 4 个单元格的平均值)。

  • myself
cpp 复制代码
class Solution {
public:
    vector<vector<int>> imageSmoother(vector<vector<int>>& img) {
        //我现在没想到什么好的办法直接遍历然后逐个判断周边情况
        int row=img.size();
        int col=img[0].size();
        vector<vector<int>>ans(row,vector<int>(col));

        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col;j++)
            {
                //逐个判断周边情况
                int sum=0;
                int count=1;//记录格子数量
                //自己
                sum+=img[i][j];

                //判断左边是否有值
                if(j>=1)
                {
                    sum+=img[i][j-1];
                    count++;
                }
                //判断是否有右值
                if(j<col-1)
                {
                    sum+=img[i][j+1];
                    count++;
                }

                //判断是否有下值
                if(i<row-1)
                {
                    sum+=img[i+1][j];
                    count++;
                }

                //判断是否有上值
                if(i>=1)
                {
                    sum+=img[i-1][j];
                    count++;
                }

                //判断左下值
                if(j>=1&&i<row-1)
                {
                    sum+=img[i+1][j-1];
                    count++;
                }

                //判断右下值
                if(j<col-1&&i<row-1)
                {
                    sum+=img[i+1][j+1];
                    count++;
                }

                //判断左上值
                if(j>=1&&i>=1)
                {
                    sum+=img[i-1][j-1];
                    count++;
                }

                //判断右上值
                if(j<col-1&&i>=1)
                {
                    sum+=img[i-1][j+1];
                    count++;
                }
                

                ans[i][j]=sum/count;
            }
        }
        return ans;
    }
};
  • 解析
cpp 复制代码
class Solution {
public:
    vector<vector<int>> imageSmoother(vector<vector<int>>& img) {
        int m = img.size(), n = img[0].size();
        vector<vector<int>> ret(m, vector<int>(n));
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int num = 0, sum = 0;
                for (int x = i - 1; x <= i + 1; x++) {
                    for (int y = j - 1; y <= j + 1; y++) {
                        if (x >= 0 && x < m && y >= 0 && y < n) {
                            num++;
                            sum += img[x][y];
                        }
                    }
                }
                ret[i][j] = sum / num;
            }
        }
        return ret;
    }
};

题目733:图像渲染(NO)

  • 广度优先遍历,每当检查一个队列里的节点时,都会检查其周边节点是否满足条件,满足就进入。

有一幅以 m x n 的二维整数数组表示的图画 image ,其中 image[i][j] 表示该图画的像素值大小。

你也被给予三个整数 sr , sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进行 上色填充 。

为了完成 上色工作 ,从初始像素开始,记录初始坐标的 上下左右四个方向上 像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应 四个方向上 像素值与初始坐标相同的相连像素点,......,重复该过程。将所有有记录的像素点的颜色值改为 newColor 。

最后返回 经过上色渲染后的图像 。

cpp 复制代码
class Solution {
public://           上 下 左   右
    const int dr[4]={-1, 1, 0,  0 };
    const int dc[4]={ 0, 0, -1, 1};
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {
        
        int max_row=image.size();
        int max_col=image[0].size();
        //使用广度优先遍历,用队列
        int current_color=image[sr][sc];
        if(color==current_color)
        {
            //如果第一个要修改的值就不满足修改条件,返回
            return image;
        }

        queue<pair<int,int>>que;
        //先将自身节点入队
        //pair<int,int>p={sr,sc};
        que.push(pair<int,int>(sr,sc));

        //不为空则循环执行
        while(!que.empty())
        {   
            auto front=que.front();
            int row=front.first;
            int col=front.second;

            //修改自身的值
            image[row][col]=color;

            //出队
            que.pop();

            //每个元素四个方向都要检查
            for(int i=0;i<4;i++)
            {
                //dx和dy可以显示上下左右的值
                int index_row=row+dr[i];
                int index_col=col+dc[i];

                //判断是否符合条件
                if(index_row>=0&&index_row<max_row&&index_col>=0&&index_col<max_col
                &&image[index_row][index_col]==current_color)
                {
                    //满足条件,入队
                    que.push(pair<int,int>(index_row,index_col));
                }
            }

        }

        return image;


    }
};

题目766:托普利兹矩阵(YES)

  • 解题思路:直接两层for先遍历一遍所有元素,并再遍历的过程中检查每个元素的右下角的值是否等于当前值,如果不等,则不满足条件,直接返回即可。

给你一个 m x n 的矩阵 matrix 。如果这个矩阵是托普利茨矩阵,返回 true ;否则,返回 false 。

如果矩阵上每一条由左上到右下的对角线上的元素都相同,那么这个矩阵是 托普利茨矩阵 。

  • myself
cpp 复制代码
class Solution {
public:
		//这里增量的设置其实是多余的,我只是想巩固一下这一专题的解题套路
        const int dr=1;
        const int dc=1;//定义右下角的增量
    bool isToeplitzMatrix(vector<vector<int>>& matrix) {
       
        int row=matrix.size();
        int col=matrix[0].size();

        for(int i=0;i<row;i++)
        {
            for(int j=0;j<col;j++)
            {
                //遍历每一个元素,并判断每个一的右下角的值是相同
                //如果不同则直接返回false,如果没有,则继续判断
                int current_row=i+dr;
                int current_col=j+dc;
                if(current_row<row&&current_col<col&&
                matrix[i][j]!=matrix[current_row][current_col])
                {
                    //右下角不相等,返回false
                    return false;
                }
            }
        }
        return true;
    }
};

题目832:翻转图像(YES)

  • 解题思路:一次for遍历每一个容器,然后对每一个容器使用双指针进行翻转操作,翻转的同时使用^(异或)运算对值进行改变(1-0,0-1)

给定一个 n x n 的二进制矩阵 image ,先 水平 翻转图像,然后 反转 图像并返回 结果 。

水平翻转图片就是将图片的每一行都进行翻转,即逆序。

例如,水平翻转 [1,1,0] 的结果是 [0,1,1]。

反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。

例如,反转 [0,1,1] 的结果是 [1,0,0]。

  • myself
cpp 复制代码
class Solution {
public:
    vector<vector<int>> flipAndInvertImage(vector<vector<int>>& image) {
        //这里反转的思路我打算使用双指针来操作,并在反转的过程中对值进行修改

        int n=image.size();

        for(int i=0;i<n;i++)
        {
            //对每一个容器进行双指针操作
            int left=0;
            int right=n-1;
            while(left<=right)
            {
                //先修改值再交换元素,使用异或运算
                if(left!=right)
                {
                    image[i][left] ^=1;
                    image[i][right]^=1;
                }else
                {
                    image[i][left]^=1;
                }
                

                //交换两个元素
                swap(image[i][left],image[i][right]);
                left++;
                right--;
                 
            }
        }
        return image;
    }
};

专题5:枚举

题目1534:统计好三元组(NO)

  • 解题思路:这题直接三层for就可以直接暴力解决了,当时让我感到疑惑的一个点是三层for为什么就可以遍历完所有的三元组了。

给你一个整数数组 arr ,以及 a、b 、c 三个整数。请你统计其中好三元组的数量。

如果三元组 (arr[i], arr[j], arr[k]) 满足下列全部条件,则认为它是一个 好三元组 。

0 <= i < j < k < arr.length

|arr[i] - arr[j]| <= a

|arr[j] - arr[k]| <= b

|arr[i] - arr[k]| <= c

其中 |x| 表示 x 的绝对值。

返回 好三元组的数量 。

cpp 复制代码
class Solution {
public:
    int countGoodTriplets(vector<int>& arr, int a, int b, int c) {
        //直接暴力三层for
        int ans=0;
        for(int i=0;i<arr.size();i++)
        {
            for(int j=i+1;j<arr.size();j++)
            {
                for(int k=j+1;k<arr.size();k++)
                {
                    //判断是否满是条件
                    if(abs(arr[i]-arr[j])<=a&&abs(arr[j]-arr[k])<=b
                    &&abs(arr[i]-arr[k])<=c)
                    {
                        ans++;
                    }
                }
            }
        }
        return ans;
    }
};

题目1566:重复至少k次且长度为M的模式(NO)

  • 解题思路:直接暴力的思路,遍历所有的模式,并且存储当前的模式,与后面连续的模式进行比较,看是否满足条件

给你一个正整数数组 arr,请你找出一个长度为 m 且在数组中至少重复 k 次的模式。

模式 是由一个或多个值组成的子数组(连续的子序列),连续 重复多次但 不重叠 。 模式由其长度和重复次数定义。

如果数组中存在至少重复 k 次且长度为 m 的模式,则返回 true ,否则返回 false 。

cpp 复制代码
class Solution {
public:
    bool containsPattern(vector<int>& arr, int m, int k) {
        int len = arr.size();

        //如果输入长度连一次模式匹配的长度都没有,必然是错误的
        if (len < m) 
        {
            return false;
        }
        
        //遍历每一个模式
        for (int i = 0; i <= len - m; i++) 
        {
            vector<int> pattern(m);//存储当前的模式
            for (int j = 0; j < m; j++) 
            {
                pattern[j] = arr[i + j];
            }
            
            int count = 1;//自己的模式算一个
            for (int p = i + m; p <= len - m; p += m) 
            {//从下一个模式开始匹配
                bool matched = true;
                for (int q = 0; q < m; q++) 
                {
                    //逐一比较里面的元素
                    if (arr[p + q] != pattern[q]) 
                    {
                        matched = false;
                        break;
                    }
                }
                if (matched) 
                {
                    count++;
                    if (count == k) 
                    {
                        return true;
                    }
                } else 
                {
                    //这里要求要连续,不连续则匹配下一个
                    break;
                }
            }
        }
        
        return false;
    }
};
相关推荐
爱吃生蚝的于勒1 小时前
C语言内存函数
c语言·开发语言·数据结构·c++·学习·算法
ChoSeitaku6 小时前
链表循环及差集相关算法题|判断循环双链表是否对称|两循环单链表合并成循环链表|使双向循环链表有序|单循环链表改双向循环链表|两链表的差集(C)
c语言·算法·链表
DdddJMs__1356 小时前
C语言 | Leetcode C语言题解之第557题反转字符串中的单词III
c语言·leetcode·题解
Fuxiao___7 小时前
不使用递归的决策树生成算法
算法
我爱工作&工作love我7 小时前
1435:【例题3】曲线 一本通 代替三分
c++·算法
白-胖-子7 小时前
【蓝桥等考C++真题】蓝桥杯等级考试C++组第13级L13真题原题(含答案)-统计数字
开发语言·c++·算法·蓝桥杯·等考·13级
workflower7 小时前
数据结构练习题和答案
数据结构·算法·链表·线性回归
好睡凯7 小时前
c++写一个死锁并且自己解锁
开发语言·c++·算法
Sunyanhui17 小时前
力扣 二叉树的直径-543
算法·leetcode·职场和发展
一个不喜欢and不会代码的码农7 小时前
力扣105:从先序和中序序列构造二叉树
数据结构·算法·leetcode