试题A:门牌制作
解题思路
从[1,2020]循环,一直累加计算即可。
代码示例
public class 门牌制作 {
public static void main(String[] args) {
int sum = 0;
for (int i = 1; i <= 2020; i++) {
int x = i;
while (x > 1){
if(x % 10 == 2)
sum++;
x /= 10;
}
}
System.out.println(sum);
}
}
答案
624
试题B:寻找2020
解题思路
定义二维矩阵,遍历每个坐标,
代码示例
import java.util.Scanner;
public class B寻找2020 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int n=300,cnt=0;
char c[][]=new char[n][n];
for(int i=0;i<n;i++)
c[i]=sc.next().toCharArray();
int dir[][]={{0,1},{1,0},{1,1}};
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(c[i][j]!='2')continue;
for(int d=0;d<dir.length;d++){
if(i+3*dir[d][0]>=n||j+3*dir[d][1]>=n)continue;
if(c[i+dir[d][0]][j+dir[d][1]]=='0'&&c[i+2*dir[d][0]][j+2*dir[d][1]]=='2'&&c[i+3*dir[d][0]][j+3*dir[d][1]]=='0'){
cnt++;
}
}
}
}
System.out.println(cnt);
}
}
试题C:蛇形填数
解题思路
第一行第一列 :1 1
第二行第二列: 5 1 + 1 x 4
第三行第三列: 13 1 + 1 x 4 + 2 x 4
...
由此可得:
第n行第n列: 1 + 1 x 4 + 2 x 4 + ... +(n -1) x 4 = 2n(n-1)+1
代码示例##
public class C蛇形填数 {
public static void main(String[] args) {
int n = 20;
System.out.println("(2 * n * (n - 1) + 1) = " + (2 * n * (n - 1) + 1));
}
}
答案:
761
试题D:七段码
解题思路
1、对a、b、c、d、e、f、g进行全排列,写满草稿纸,注意正确率;
2、(1)、将数码管的七段进行全排列(用数字代表数码管字段,0代表a,1代表b,以此类推)然后将这7个数字的所有可能全 部排列(从7个数字中取m(1<=m<=7)进行排列)列举出来。
(2)、得到所有的取值情况,再判断每种情况构成的图是否连通,若连通,sum++
(3)、进行排列时需要注意,一定要保证每个排列必须是递增或者递减,这样才能不重复,例如:012,021,210等等,它们都表示数码管中取出ABC这一种情况。
代码示例
package provincialGames_11_2020_2_JavaB;
public class _04_D_七段码 {
static boolean[][] M;// M是邻接矩阵
static int[] a;// a代表排列组合的数字
static int sum = 0;// 最后结果
public static void main(String[] args) {
/*
* M是邻接矩阵,根据数码管图像可以得到 例如:a和b,a和f都可以连通,那么代表0和1,0和5连通
*/
M = new boolean[7][7];
M[0][1] = M[1][0] = M[0][5] = M[5][0] = true;
M[1][2] = M[2][1] = M[1][6] = M[6][1] = true;
M[2][3] = M[3][2] = M[2][6] = M[6][2] = true;
M[4][3] = M[3][4] = true;
M[4][5] = M[5][4] = M[4][6] = M[6][4] = true;
M[5][6] = M[6][5] = true;
a = new int[7];
for (int i = 0; i < a.length; i++) {
a[i] = i;
}
// 所有排列的可能,深搜
for (int n = 1; n <= 7; n++) {
dfs(0, n);
}
System.out.println(sum);
}
public static void dfs(int k, int n) {
if (k == n) {
// 如果只有一个数,那么这种情况下必然成立
if (n == 1) {
sum++;
return;
}
// 判断,这种情况下的图是否连通。用的是并查集方法
// 初始化
int[] pre = new int[n];
for (int i = 0; i < pre.length; i++) {
pre[i] = i;
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
// 两层for穷举所有边的情况
// 若i和j连通,j加入i
// i和j代表的是结点,所以并的时候就是jion(pre,
// i,j)。但是i代表的结点好j代表的结点是否连通,则需要看a[i]]和[a[j]在邻接矩阵M中是否为真
if (M[a[i]][a[j]]) {
jion(pre, i, j);
}
}
}
// 到最后,若所有结点都连通,则所有结点的跟结点应该都一样。否则说明此情况下的图不连通
boolean flag = true;
for (int i = 1; i < pre.length; i++) {
if (find(pre, 0) != find(pre, i)) {
flag = false;
break;
}
}
if (flag) {
sum++;
}
return;
}
// dfs,深搜
for (int i = k; i < a.length; i++) {
if (k == 0 || a[i] > a[k - 1]) {
int t = a[i];
a[i] = a[k];
a[k] = t;
dfs(k + 1, n);
t = a[i];
a[i] = a[k];
a[k] = t;
}
}
}
// 查找根节点
public static int find(int[] pre, int node) {
int son = node, temp = 0;
// 查找根节点
while (node != pre[node]) {
node = pre[node];
}
// 路径优化
while (son != node) {
temp = pre[son];
// 直接通跟
pre[son] = node;
// son向上走一格
son = pre[son];
}
return node;
}
// 两个结点相并
public static void jion(int[] pre, int x, int y) {
int fx = find(pre, x);
int fy = find(pre, y);
// 两个结点属于不同图,相并
if (fx != fy) {
pre[fy] = fx;
}
}
}
试题E:排序
解题思路
1、找规律
冒泡排序中我发现的规律如下:
比较的物体长度 | 比较次数 |
---|---|
1 | 0 |
2 | 1 |
3 | 2 |
4 | 1 + 2 + 3 |
5 | 1 + 2 + 3 + 4 |
… | … |
n | n(n - 1) / 2 |
2、计算最小字母序列长度
n * (n - 1) / 2 >= 100
得出n最小为15;
然而n = 15 时假设这个不重复的字符串是字典序最小的反向排列即为:onmlkjihgfedcba,此字符串需要比较 (15 x 14)/ 2 = 105次;
此时,需要逆向思维一下:在比较次数固定的情况下,需要减少移动次数,只需要考虑在原字符串的基础上,将需要减少的次数的位数上的字符移动到字符串最前面减少移动次数即可。所以将字符串onmlkjihgfedcba
中第六位j
移到最前面,变成 jonmlkihgfedcba
每次j会分别和o,n,m,l,k进行比较,但是不交换,这样就省下了5次交换,且最后一共交换105-5=100次。
最终结果
jonmlkihgfedcba
小贴士:
- 字符串的反转代码:
public class Test {
public static void main(String[] args) {
String s = "abcdefghijklmno";
String rs = new StringBuilder(s).reverse().toString();
System.out.println(rs);
}
}
- 字典序:字典序是指从前到后比较两个字符串的大小的方法。
试题F:成绩分析
解题思路
- Scanner方法的应用与循环输入;
- 最大值,最小值,平均数的求法;
- 格式化输出;
代码示例
public class F_成绩分析 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] scores = new int[n];
for (int i = 0; i < n; i++) {
scores[i] = scanner.nextInt();
}
M(scores);
}
private static void M(int[] nums){
int max = nums[0];
int min = nums[0];
double sum = 0;
int tem;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
if (nums[i] > max){
tem = nums[i];
nums[i] = max;
max = tem;
}
if (nums[i] < min){
tem = nums[i];
nums[i] = min;
min = tem;
}
}
System.out.println(max);
System.out.println(min);
System.out.println(String.format("%.2f", sum/nums.length));
}
}
试题G:单词分析
解题思路
- 从键盘输入字符串使其以字符的方式存储;
- 将字符与数组相结合,灵活转换,记录字符的出现次数。
代码示例
public class G_单词分析 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
char[] chars = scanner.nextLine().toCharArray();
int[] counts = new int[26]; // 使用其默认值,对后续出现的字母进行统计
for (int i = 0; i < chars.length; i++) {
counts[chars[i] - 'a']++; // 出现相同的字母进行累加,只要出现就会被记录
}
int val = counts[0];
int index = 0;
for (int i = 0; i < counts.length; i++) {
if(counts[i] > val){
val = counts[i]; // 将数组中值最大的取出来
index = i;
}
}
System.out.println((char) (index + 'a'));
System.out.println(val);
}
}
试题H:数字三角形
解题思路:
DP推导+奇偶判断
示例代码
import java.util.Scanner;
public class H {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=scanner.nextInt();
int arr[][]=new int[n+1][n+1];
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
arr[i][j]=scanner.nextInt();
arr[i][j]+=Math.max(arr[i-1][j-1], arr[i-1][j]);
}
}
System.out.println(n%2==1?arr[n][n/2+1]:Math.max(arr[n][n/2], arr[n][n/2+1]));
}
}
试题I:字串分值和
解题思路
暴力求解
示例代码
import java.util.*;
public class I {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
String string=scanner.next();
char c[]=string.toCharArray();
long ans=0;
for(int i=0;i<c.length;i++){
HashSet<Character> set=new HashSet<Character>();
for(int j=i;j<c.length;j++){
set.add(c[j]);
ans+=set.size();
}
}
System.out.println(ans);
}
}
试题J:装饰珠
解题思路
。。。
代码示例
。。。