2.10
给你一个整数 n
,请你返回所有 0 到 1 之间(不包括 0 和 1)满足分母小于等于 n
的 最简 分数 。分数可以以 任意 顺序返回。
这里要搞清楚最简分数的定义,也就是分子分母的最大公约数为1的分数,因为我们i/j递增,可以确保不会有重复分数,只需要满足最简即可,想要计算最大公约数,我们使用欧几里得算法gcd,
也就是gcd(x,y)=gcd(y,x%y),如果xy可以整除返回较小数即可,我们始终保证大数在前。
class Solution {
public List<String> simplifiedFractions(int n) {
List<String>ans=new ArrayList<>();
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
if(gcd(j, i)==1)
ans.add(i+"/"+j);
}
}
return ans;
}
int gcd(int x,int y){
if(x%y==0)return y;
return gcd(y,x%y);
}
}
2.11
给你一个 下标从 0 开始 的整数数组 nums ,其中 nums[i] 表示第 i 名学生的分数。另给你一个整数 k 。
从数组中选出任意 k 名学生的分数,使这 k 个分数间 最高分 和 最低分 的 差值 达到 最小化 。
返回可能的 最小差值 。
class Solution {
public int minimumDifference(int[] nums, int k) {
//剪枝
if(k==1)return 0;
//升序排列,我们选定一个大小为k的滑动窗口
//窗口两端的数值差,对应当前窗口极差
//最小极差即为我们所求答案
Arrays.sort(nums);
int n=nums.length,ans=Integer.MAX_VALUE;
for(int i=0;i<=n-k;i++){
ans=Math.min(ans,nums[i+k-1]-nums[i]);
}
return ans;
}
}
2.12
给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。
一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。
返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。
方法:多源BFS
统计所有陆地块数cnt,从边界的陆地开始BFS,每找到一块陆地,cnt--即可
class Solution {
int[][]dirs=new int[][]{{0,1},{0,-1},{1,0},{-1,0}};
public int numEnclaves(int[][] grid) {
int m=grid.length,n=grid[0].length;
//防止重复访问
boolean[][]visited=new boolean[m][n];
//首先记录所有陆地数目
int cnt=0;
//BFS搜索所有在边界的陆地
//总数目-边界可达陆地数=飞地数目
Deque<int[]>queue=new LinkedList<>();
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==1){
cnt++;
if(i==0||i==m-1||j==0||j==n-1){
queue.offer(new int[]{i,j});
visited[i][j]=true;
}
}
}
}
System.out.println("陆地块数"+cnt);
while(!queue.isEmpty()){
//可以连接到边界的陆地,数目--
int[]cur=queue.poll();
int x=cur[0],y=cur[1];
System.out.println("可达陆地坐标("+x+","+y+")");
cnt--;
for(int[]dir:dirs){
int dx=x+dir[0],dy=y+dir[1];
if(dx<0||dx>=m||dy<0||dy>=n)continue;
if(visited[dx][dy])continue;
if(grid[dx][dy]==1){
queue.offer(new int[]{dx,dy});
visited[dx][dy]=true;
}
}
}
return cnt;
}
}