6051. 统计是给定字符串前缀的字符串数目
https://leetcode-cn.com/problems/count-prefixes-of-a-given-string/
思路:遍历words数组,利用字符串中的startWith()方法即可
class Solution {
public int countPrefixes(String[] words, String s) {
int cnt=0;
for(String word:words) {
if(s.startsWith(word))
cnt++;
}
return cnt;
}
}
//O(kn) k是words数组中单词的平均长度
//O(1)
6052. 最小平均差
https://leetcode-cn.com/problems/minimum-average-difference/
思路:简单模拟题,遍历到某个下标i时,只需要知道nums[0…i]和nums[i+1,n-1]的和即可,然后求平均值。为了方便获得当前位置的累加和,利用前缀和数组,这样可以容易地获得nums[0…i]元素之和,对于nums[i+1,n-1]元素和可以利用总的和减去nums[0…i]元素之和获取。
注意点:和的数值可能很大,使用long类型,不然会数据溢出
class Solution {
public int minimumAverageDifference(int[] nums) {
int n=nums.length;
long totalSum=0;
long[] pre=new long[n+1];
for(int i=0;i<n;i++) {
pre[i+1]=pre[i]+nums[i];
totalSum+=nums[i];
}
int ans=-1;
long minDif=Integer.MAX_VALUE;
for(int i=0;i<n;i++) {
long sum1=pre[i+1];
long sum2=totalSum-sum1;
long ave1=sum1/(i+1);
long ave2=n-i-1==0?0:sum2/(n-i-1);
long dif=Math.abs(ave1-ave2);
if(dif<minDif) {
minDif=dif;
ans=i;
}
}
return ans;
}
}
//O(n)
//O(n)
6053. 统计网格图中没有被保卫的格子数
https://leetcode-cn.com/problems/count-unguarded-cells-in-the-grid/
思路:dfs, 和一般的dfs不同,这里的dfs都是直来直往,没有拐弯抹角。使用一个visited数组记录网格中不同格子的情况,先根据guards数组和walls数组进行初始化,有警卫的位置用1表示,有墙的地方用2表示;然后遍历网格,遇到1时(警卫),开始向4个方向dfs搜索,对于可以看到的位置,在visited数组中用3表示,防止重复访问。遍历结束只会,判断visited数组中为0的个数即可
class Solution {
int[][] visted;
int m,n;
int[][] g;
int[][] w;
public int countUnguarded(int m, int n, int[][] guards, int[][] walls) {
visted=new int[m][n];
for(int[] guard:guards) {
int i=guard[0];
int j=guard[1];
visted[i][j]=1;
}
for(int[] wall:walls) {
int i=wall[0];
int j=wall[1];
visted[i][j]=2;
}
this.m=m;
this.n=n;
this.g=guards;
this.w=walls;
for(int i=0;i<m;i++) {
for(int j=0;j<n;j++) {
if(visted[i][j]==1) {
dfs1(i+1,j);
dfs2(i-1,j);
dfs3(i, j+1);
dfs4(i, j-1);
}
}
}
int ans=0;
for(int i=0;i<m;i++) {
for(int j=0;j<n;j++)
if(visted[i][j]==0)
ans++;
}
return ans;
}
public void dfs1(int i,int j) {//向下看
if(i<0||i>=m||j<0||j>=n||visted[i][j]==1||visted[i][j]==2)
return;
visted[i][j]=3;
dfs1(i+1,j);
}
public void dfs2(int i,int j) {//向上看
if(i<0||i>=m||j<0||j>=n||visted[i][j]==1||visted[i][j]==2)
return;
visted[i][j]=3;
dfs2(i-1,j);
}
public void dfs3(int i,int j) {//向右看
if(i<0||i>=m||j<0||j>=n||visted[i][j]==1||visted[i][j]==2)
return;
visted[i][j]=3;
dfs3(i,j+1);
}
public void dfs4(int i,int j) {//向左看
if(i<0||i>=m||j<0||j>=n||visted[i][j]==1||visted[i][j]==2)
return;
visted[i][j]=3;
dfs4(i,j-1);
}
}
//O(mn) 每个格子最多只会被遍历一次
//O(mn)
6054. 逃离火灾
https://leetcode-cn.com/problems/escape-the-spreading-fire/
思路:BFS+二分
几个关键点:
- 只保存新蔓延到的着火点
- 新蔓延到的着火的在每一次bfs后都要更新
class Solution {
int[][] dirs={{0,-1},{0,1},{-1,0},{1,0}};//方向数组
public int maximumMinutes(int[][] grid) {
int m=grid.length,n=grid[0].length;
int left=0,right=m*n;//最少最多的停留时间
boolean canEscape=false;
while(left<=right){
//int mid=left+(right-left)/2;
int mid=(left+right)/2;
if(check(grid,mid)){
left=mid+1;//安全->时间再待久一点
canEscape=true;
}
else
right=mid-1;
}
if(!canEscape)//没有成功过
return -1;
else
return left<m*n?left-1:(int)1e9;
//0--left-1时间都是安全的 left时间不安全
}
public boolean check(int[][] grid,int minutes){
int m=grid.length,n=grid[0].length;
boolean[][] fire=new boolean[m][n];//表示某个位置是否有火
ArrayList<int[]> firePoints=new ArrayList<>();//记录着火点
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==1){//网格值为1表示起火
fire[i][j]=true;//(i,j)位置着火
firePoints.add(new int[]{i,j});
}
}
}
while(minutes>0&&firePoints.size()>0){//蔓延minutes分钟的火势 并且有蔓延点
firePoints=spreadFire(grid,fire,firePoints);//firePoints保存新蔓延到的着火点
minutes--;
}
boolean[][] vis=new boolean[m][n];
ArrayList<int[]> q=new ArrayList<>();
q.add(new int[]{0,0});
vis[0][0]=true;
while(q.size()>0){
ArrayList<int[]> tmp=q;
q=new ArrayList<>();
for(int[] point:tmp){
if(!fire[point[0]][point[1]])//当前位置未着火
for(int[] dir:dirs){
int x=point[0]+dir[0];
int y=point[1]+dir[1];
if(x>=0&&x<m&&y>=0&&y<n&&!fire[x][y]&&grid[x][y]!=2&&!vis[x][y]){
if(x==m-1&&y==n-1)//达到右下角
return true;
vis[x][y]=true;
q.add(new int[]{x,y});//当前可以达到的未着火点 经过后面传播可以着火
}
}
}
firePoints=spreadFire(grid,fire,firePoints);//蔓延1分钟的火势
}
return false;
}
public ArrayList<int[]> spreadFire(int[][] grid, boolean[][] fire, ArrayList<int[]> firePoints) {
int m=grid.length,n=grid[0].length;
ArrayList<int[]> newFirePoints=new ArrayList<>();//新传播到的着火点
for(int[] firePoint:firePoints){
for(int[] dir:dirs){
int x=firePoint[0]+dir[0];
int y=firePoint[1]+dir[1];
if(x>=0&&x<m&&y>=0&&y<n&&grid[x][y]!=2&&!fire[x][y]){//不出边界+不是墙+之前没有被点着
fire[x][y]=true;
newFirePoints.add(new int[]{x,y});
}
}
}
return newFirePoints;
}
}