💐今日学习💐
目录
🎈第一题
🎯问题描述:
以下是一个 25 行 25 列的字母矩阵,全部由字母 A 和 B 组成。 AAAAAAABABBAABABABAAAAAAA ABBBBBABBAABBBBBABABBBBBA ABAAABABBBABAABBBBABAAABA ABAAABABBBBBAABAABABAAABA ABAAABABBABABBABABABAAABA ABBBBBABBBABAABBBBABBBBBA AAAAAAABABABABABABAAAAAAA BBBBBBBBABAABABBBBBBBBBBB AABAABABBAAABBAAABABBBBBA ABBABABBBABBAAAABBBBAAAAB BBBBAAABABAABABAABBBAABBA BBAABABABAAAABBBAABBAAAAA ABABBBABAABAABABABABBBBBA AAAABBBBBABBBBAAABBBABBAB AABAABAAABAAABAABABABAAAA ABBBBBBBBABABBBBABAABBABA ABBBAAABAAABBBAAAAAAABAAB BBBBBBBBABBAAABAABBBABBAB AAAAAAABBAAABBBBABABAABBA ABBBBBABBAABABAAABBBABBAA ABAAABABABBBAAAAAAAAAABAA ABAAABABABABBBABBAABBABAA ABAAABABBABBABABAABAABAAA ABBBBBABABBBBBABBAAAABAAA AAAAAAABAABBBAABABABBABBA 请问在这个矩阵中有多少个字母A?
import java.util.Scanner;
public class demo {
public static void main(String[] args) {
int count=0;
Scanner sc=new Scanner(System.in);
char a[][]=new char[25][25];
for (int i = 0; i <25; i++) {
String s=sc.next();
for (int j = 0; j < 25; j++) {
a[i][j]=s.charAt(j);
if (a[i][j]=='A'){
count++;
}
}
}
System.out.println(count);
}
}
🎃题解分析:
1)首先是输入一个25*25的矩阵
其中矩阵是char类型的,输入的时候是String类型字符串,获取用的是charAt()方法
2判断元素是否等于字符A
🎈第二题
🎯问题描述:
如果一个整数的某个数位包含 2 ,则称这个数为一个“最2数字”。例如:102、2021 都是最2数字。
请问在 1(含) 到 2021(含) 中,有多少个最2数字。
public class demo2 {
public static void main(String[] args) {
int count=0;
for (int i = 1; i <=2021 ; i++) {
String s=i+"";
if (s.contains("2")){
count++;
}
}
System.out.println(count);
}
}
🎃题解分析:
1)遍历
2)转化为字符串
3)使用字符串中的contains方法判断
🎈第三题
🎯问题描述:
有一个整数 A=2021,每一次,可以将这个数加 1 、减 1 或除以 2,其中除以 2 必须在数是偶数的时候才允许。例如,2021 经 过一次操作可以变成 2020、2022。再如,2022 经过一次操作可以变成 2021、2023 或 1011。请问,2021 最少经过多少次操作可以变成 1。
import java.util.LinkedList;
import java.util.Queue;
public class demo3 {
public static void main(String[] args) {
Queue<Integer> q = new LinkedList<>();
int ans = 0;
boolean[] A = new boolean[10000];
q.offer(2021);
A[2021]=true;
int i;
while (!q.isEmpty()) {
for (int j = q.size(); j >0 ; j--) {
//for(int j=0;j<q.size(),j++)注意q.size()的值不是一个定值,在循环过程中会发生变化
i = q.poll();
if (i == 1) {
System.out.println(ans);
return;
}
if (!A[i + 1]) {
A[i + 1] = true;
q.offer(i + 1);
}
if (!A[i - 1]) {
A[i - 1] = true;
q.offer(i - 1);
}
if (!A[i / 2] && i % 2 == 0) {
A[i / 2] = true;
q.offer(i / 2);
}
}
ans++;
}
}
}
🎃题解分析:
这题是最短路径问题,我是纯手算的,上面贴了代码,目前还不是很清楚。
(1)题目问的是最少次数,其实我们仔细想想就会发现这个其实就是最短路径问题
(2)最短路径问题我们用的是BFS,与BFS相关的数据结构我们要马上想到是队列
(3)我们分析一下上图,首先我们把2021放入队列中,然后给队列头2021进行poll(去队列头,并删除该队列头),并按题目要求进行+1、-1、/2操作得到2022、2020,这个时候把2022、2020又放入队列中(上图中每一行的元素在同一个队列),重复操作,当队列中出现1时输出次数(这个时候一定是操作次数最少的)
(4)注意事项:我们要对每一个入队的元素进行标记(使用boolean数组),避免重复冗余操作,优化复杂度
🎈第四题
🎯问题描述:
对于一个 n 行 m 列的表格,我们可以使用螺旋的方式给表格依次填上正整数,我们称填好的表格为一个螺旋矩阵。 例如,一个 4 行 5 列的螺旋矩阵如下: 1 2 3 4 5 14 15 16 17 6 13 20 19 18 7 12 11 10 9 8 请问,一个 30 行 30 列的螺旋矩阵,第 20 行第 20 列的值是多少?
public class demo4 {
static int[][] A = new int[30][30];
public static void main(String[] args) {
generateMatrix(30);
System.out.println(A[19][19]);
}
static public void generateMatrix(int n) {
int t = 0, l = 0;//上边界和左边界
int b = n - 1, r = n - 1;//下边界和右边界
int num = 1;
while (num < n * n) {
for (int i = l; i <= r; i++) {//在tpo层从左到右遍历赋值
A[t][i] = num++;
}
t++;//最上层遍历后,以倒数第二层为顶层
for (int i = t; i <= b; i++) {//在r层从上到下遍历赋值
A[r][i] = num++;
}
r--;//最右层遍历后以倒数第二右层为最右层
for (int i = r; i >= l; i--) {//在b层从右到左遍历赋值
A[b][i] = num++;
}
b--;//最底层遍历后以倒数第二底层为最底层
for (int i = b; i >= t; i--) {//在l层从下到上遍历赋值
A[i][l] = num++;
}
l++;//最左层遍历后以倒数第二左层为最左层
}
}
}
🎃题解分析:
(1)这个题目,博主也是第一次做,刚开始难免会有一些蒙蔽,后面去leetcode上参考了一下各路神仙的解法,瞬间就豁然开朗
(2)首先先定义一个二维数组A用来存储所有的数据,这样子当你想知道n行m列的值时就可以直接输出An-1即可
(3)接下来我们分析一下怎么螺旋存储数据,如上图所示,我们结合代码来一起分析:
t++:当我遍历完第一行时,此时第二层变为最顶层
r--:当我们遍历完最右层时,倒数第二右层变为最右层
b--:当我们遍历完最底层时,倒数第二层变为最底层
l++:当我们遍历完最左层时,倒数第二左层变为最左层
哈哈哈,是不是有种“套娃”的感觉,我们其实每遍历存储一层数据,剩下未填数字的数组大小就缩水一圈,结合图形一起就会变得非常好理解。
🎈第五题
🎯问题描述:
一棵二叉树有2021个结点。该树满足任意结点的左子树结点个数和右子树的结点个数之差最多为1。 定义根结点的深度为0,子结点的深度比父结点深度多1。 请问,树中深度最大的结点的深度最大可能是多少?
public class demo4 {
static int[][] A = new int[30][30];
public static void main(String[] args) {
generateMatrix(30);
System.out.println(A[19][19]);
}
static public void generateMatrix(int n) {
int t = 0, l = 0;//上边界和左边界
int b = n - 1, r = n - 1;//下边界和右边界
int num = 1;
while (num < n * n) {
for (int i = l; i <= r; i++) {//在tpo层从左到右遍历赋值
A[t][i] = num++;
}
t++;//最上层遍历后,以倒数第二层为顶层
for (int i = t; i <= b; i++) {//在r层从上到下遍历赋值
A[r][i] = num++;
}
r--;//最右层遍历后以倒数第二右层为最右层
for (int i = r; i >= l; i--) {//在b层从右到左遍历赋值
A[b][i] = num++;
}
b--;//最底层遍历后以倒数第二底层为最底层
for (int i = b; i >= t; i--) {//在l层从下到上遍历赋值
A[i][l] = num++;
}
l++;//最左层遍历后以倒数第二左层为最左层
}
}
}
🎃题解分析:
这个题目有点难搞,由于博主数据结构这块学的不够深入,所以我在这里仅阐述我的两种思路,有会做的小伙伴,欢迎私信和留言✏️!
思路一:
将该题目看成一个完全二叉树(完全二叉树肯定满足题目条件)
公式:2^(n-1)-1<=2021<=2^(n)-1,算出n=11,因为第一层深度0,所以深度为10
不过我总感觉题目没有这么简单,下面来说一下思路二。
思路二:
将该题目看成一个平衡二叉树的题目来做,对于平衡二叉树博主掌握的不是很到位,详情可以参考这篇博客:平衡二叉树
关于平衡二叉树的地推公式请参考这篇博客:平衡二叉树的最大深度和最少节点数
得到公式:S(h) = S(h-1) + S(h-2) + 1 ==>算出来是15层
public class demo5 { public static void main(String[] args) { for (int i = 0; i < 20; i++) { if ( S(i + 1) >= 2021) { System.out.println(i); return; } } } static int S(int h) { if (h == 1) return 1; if (h == 2) return 2; return S(h - 1) + S(h - 2) + 1; } }
🎈第六题
🎯问题描述:
一个和尚要挑水,每次最多能挑 a 千克,水缸最多能装 t 千克,开始时水缸为空。 请问这个和尚最少要挑多少次可以将水缸装满?
输入格式
输入一行包含两个整数 a, t,用一个空格分隔。
输出格式
输出一行包含一个整数,表示答案。
样例输入
20 2021
样例输出
102
评测用例规模与约定
对于所有评测用例,1 <= a <= 100,1 <= t <= 10000。
import java.util.Scanner;
public class demo6 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int s=sc.nextInt(),t=sc.nextInt();
if (t%s==0){
System.out.println(t/s);
}else {
System.out.println(t/s+1);
}
}
}
🎃题解分析:
这题判断能否被整除
a.能被整除 得出答案
b.不能被整除 说明有余数 结果上+1
🎈第七题
🎯问题描述:
输入一个整数,输出这个整数的百位上的数字。
输入格式
输入一行包含一个整数 n。
输出格式
输出一行包含一个整数,表示答案。
import java.util.Scanner;
public class demo7 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = n / 100 % 10;
System.out.println(m);
}
}
🎃题解分析:
就是取出百位上的数,先除100再模10
🎈第八题
🎯问题描述:
输入格式
输入一行包含一个由千分位分隔符的数值,恰好有 2 位小数。
输出格式
输出不含千分位分隔符的数值,保留 2 位小数。
样例输入
1,234,567,890.00
样例输出
1234567890.00
import java.util.Scanner;
public class demo8 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.next();
str=str.replace(",", "");
System.out.println(str);
}
}
🎃题解分析:
用空格替换掉, 用到了string类型的replace方法
🎈第九题
🎯问题描述:
小蓝有一个插板,形状用一个 n * m 的01矩阵表示,0 表示板面,1 表示插孔。 小蓝还有一个插头,形状用一个 r * c 的01矩阵表示,0 表示没有伸出的部分,1 表示伸出的部分。插头伸出的部分必须插在插孔里面。 为了安全,插头插到面板上不能有任何部分超过插板边界(包括没有伸出的部分)。 插头和插板都不能旋转,也不能翻转。请求出插头插入插板的合理位置。
输入格式
输入的第一行包含两个整数 n, m。 接下来 n 行,每行一个长度为 m 的01串,表示插板的形状。 接下来一行包含两个整数 r, c。 接下来 r 行,每行一个长度为 c 的01串,表示插头的形状。
输出格式
如果插头没办法安全插入插板中,输出“NO”。否则输出两个数 a, b,表示插头的第 1 行第 1 列对应插板的第 a 行第 b 列。如果有多种情况满足要求,输出 a 最小的方案,如果 a 最小的方案有多个,输出在 a 最小的前提下 b 最小的方案。
样例输入
3 4 0110 0000 0000 3 3 000 010 000
样例输出
NO
样例说明
在插头不超出范围的前提下无法插入。
样例输入
4 7 1110100 1101111 0001111 0000011 2 3 111 011
样例输出
2 4
评测用例规模与约定
对于 50% 的评测用例,2 <= n, m, r, c <= 20。 对于所有评测用例,2 <= n, m, r, c <= 100。
import java.util.*;
public class demo9 {
static class Node{
int x,y;
public Node(int x,int y){
this.x=x;
this.y=y;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n=scanner.nextInt();
int m=scanner.nextInt();
char A[][]=new char[n][m];
for (int i = 0; i <n ; i++) {
String s=scanner.next();
for (int j = 0; j <m ; j++) {
A[i][j]=s.charAt(j);
}
}
int r=scanner.nextInt();
int c=scanner.nextInt();
if (r > n || c > m) {
System.out.println("NO");
return;
}
char [][]B=new char[r][c];
ArrayList<Node> list=new ArrayList<>() ;
//用来存插座的坐标值
for (int i = 0; i <r ; i++) {
String s1=scanner.next();
for (int j = 0; j <c ; j++) {
B[i][j]=s1.charAt(j);
if(B[i][j]=='1'){
list.add(new Node(i,j));
}
}
}
for (int i = 0; i <n ; i++) {
for (int j = 0; j <m ; j++) {
if(A[i][j]=='1'&&i-list.get(0).x>=0&&j-list.get(0).y>=0){
//判断(i,j)是否为插头对应的插板的起始位置
boolean isTrue=true;
for (int k = 1; k <list.size() ; k++) {
//判断以(i,j)为起始位置是否符合要求
if(j+(list.get(k).y -list.get(0).y)<m&&i+(list.get(k).x -list.get(0).x)<n&&A[i+(list.get(k).x -list.get(0).x)][j+(list.get(k).y -list.get(0).y)]!='1'){
isTrue=false;
break;
}
}
if(isTrue){
System.out.print(i+1+" ");
System.out.print(j+1);
return;
}
}
}
}
System.out.println("NO");
}
}
🎃题解分析:
以上是贴的答案,以下是贴的思路,目前我还不懂。
(1)这个题目虽然放在第九题,但不是很难,听博主细细道来
(2)我们使用HashMap将a,b,c的所有约数都存进去,key值为约数,value值为该约数出现的次数,我们定义一个ans记录答案,当约数出现了两次时我们就将它视为符合题目要求的约数,ans++
(3)求约数的快速方法,两端往中间夹,可以优化一半的时间复杂度
🎈第十题
🎯问题描述:
问题描述
给定正整数 a, b, c,请问有多少个正整数,是其中至少两个数的约数。
输入格式
输入一行包含三个正整数 a, b, c。
输出格式
输出一行包含一个整数,表示答案。
import java.util.Scanner;
public class demo10 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a=sc.nextInt(),b=sc.nextInt(),c=sc.nextInt();
int max=Math.max(Math.max(a,b),c);
int count=0;
// List<Integer>list=new ArrayList<>();
for (int i = 1; i <=max ; i++) {
if ((a%i==0&&b%i==0)||(a%i==0&&c%i==0)||(b%i==0&&c%i==0)||(a%i==0&&b%i==0&&c%i==0)){
count++;
// list.add(i);
}
}
System.out.println(count);
}
}
🎃题解分析:
1)遍历最大的正整数
2)判断约数的条件是 n%i==0
🎉写在最后
博主最近看到一段话,感触颇深,送给大家:
“人生就是这样,你想得到就必须要付出
付出了还需要学会坚持,任何人的成功都不是偶然
它装满了那些人拼搏,坚持的痕迹。”
各位有志青年,加油!!