2021-12-07每日刷题打卡
力扣——每日一题
1034. 边界着色
给你一个大小为 m x n 的整数矩阵 grid ,表示一个网格。另给你三个整数 row、col 和 color 。网格中的每个值表示该位置处的网格块的颜色。
当两个网格块的颜色相同,而且在四个方向中任意一个方向上相邻时,它们属于同一 连通分量 。
连通分量的边界 是指连通分量中的所有与不在分量中的网格块相邻(四个方向上)的所有网格块,或者在网格的边界上(第一行/列或最后一行/列)的所有网格块。
请你使用指定颜色 color 为所有包含网格块 grid[row] [col] 的 连通分量的边界 进行着色,并返回最终的网格 grid 。
示例 1:
输入:grid = [[1,1],[1,2]], row = 0, col = 0, color = 3
输出:[[3,3],[3,2]]
这题并不是说所有和grid[row] [col]联通的块都要被染色,而是说既和grid[row] [col]联通,而且处于联通的边界的块才要被染色。转换一下就是,当一个色块它的上下左右四个地方的颜色都等于它时,他就不属于边界,不能够被染色,其它情况下的都算是边界(上下左右有一个或多个和自己不相同的,或者自身处于矩阵的边界等)。
这题我们用深度搜索来写,准备一个大小和grid一样的矩阵v,初始元素都设为1,从它给的坐标row col开始,每次判断当前块的上下左右,判断自身是否都和它们相等,如果有一个不相等就把这里设置为染色块,在v中把对应坐标的值设为2,如果不为染色块,就把值设为0,这是防止之后遍历的时候重复遍历这个位置,当我们遍历块的时候发现v对应坐标的值为0或2时我们就知道这个地方已经遍历过了,直接结束这次遍历。当深度搜索结束后,再遍历一遍v,当遍历到的位置上数字为2时,在grid中对应位置的块染色为color。
class Solution {
public:
int num,n,m;
vector<vector<int>> colorBorder(vector<vector<int>>& grid, int row, int col, int color) {
num=grid[row][col],n=grid.size(),m=grid[0].size();
vector<vector<int>>v(n,vector<int>(m,1));
dfs(grid,v,row,col,color);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(v[i][j]==2)grid[i][j]=color;
return grid;
}
void dfs(vector<vector<int>>& grid,vector<vector<int>>& v, int row, int col,int color)
{
if(row<0||row>=n||col<0||col>=m)return ;
if(grid[row][col]==num&&v[row][col]==1)
{
v[row][col]=0;
if(((col+1<m&&grid[row][col]!=grid[row][col+1])||col+1>=m)||
((row+1<n&&grid[row][col]!=grid[row+1][col])||row+1>=n)||
((col-1>=0&&grid[row][col]!=grid[row][col-1])||col-1<0)||
((row-1>=0&&grid[row][col]!=grid[row-1][col])||row-1<0))
v[row][col]=2;
dfs(grid,v,row,col+1,color);
dfs(grid,v,row+1,col,color);
dfs(grid,v,row-1,col,color);
dfs(grid,v,row,col-1,color);
}
return ;
}
};
力扣——剑指offer
剑指 Offer 58 - I. 翻转单词顺序
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. “,则输出"student. a am I”。
示例 1:
输入: “the sky is blue”
输出: “blue is sky the”
对撞指针,每次交换遍历到的字符。
class Solution {
public:
string reverseWords(string s) {
reverse(s.begin(), s.end());
int idx = 0, n = s.size();
for (int i = 0; i < n; i++)
{
if (s[i] != ' ')
{
if (idx != 0)s[idx++] = ' ';
int r = 0;
string str;
while (i<n&&s[i] != ' ')
{
str += s[i++];
r++;
}
while (r--)
{
s[idx++] = str[r];
}
}
}
s.erase(s.begin()+idx,s.end());
return s;
}
};
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
注:[3,1,2,4] 也是正确的答案之一。
对撞指针,当左边遍历到偶数时停下,右边遍历到奇数时停下,然后交换两指针指向的元素。
class Solution {
public:
vector<int> exchange(vector<int>& nums) {
int l=0,n=nums.size(),r=n-1;
while(l<r)
{
while(l<n&&nums[l]%2)l++;
while(r>=0&&nums[r]%2==0)r--;
if(l>=r)break;
swap(nums[l],nums[r]);
}
return nums;
}
};
剑指 Offer 57. 和为s的两个数字
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]
对撞指针,当两指针指向数字之和大于目标值时,右指针往中间走一格,小于目标值时,左指针往中间走一格。
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int l=0,n=nums.size(),r=n-1;
while(l<r)
if(nums[l]+nums[r]>target)r--;
else if(nums[l]+nums[r]<target)l++;
else return {nums[l],nums[r]};
return {};
}
};