蓝桥杯JAVA-番外篇之考前复习

本文最后更新于:April 13, 2022 pm

积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里,不积小流无以成江海。齐骥一跃,不能十步,驽马十驾,功不在舍。面对悬崖峭壁,一百年也看不出一条裂缝来,但用斧凿,能进一寸进一寸,能进一尺进一尺,不断积累,飞跃必来,突破随之。

目录

我的Java基础模板

为了方便,这里先给出我的基本模板。后面的代码都是在main函数中的,所以就不会再写这些基础的模板代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import java.io.*;
import java.util.*;

/**
* @Author DragonOne
* @Date 2021/12/5 21:27
* @墨水记忆 www.tothefor.com
*/

public class Main {
public static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
public static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
public static StreamTokenizer cin = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
public static PrintWriter cout = new PrintWriter(new OutputStreamWriter(System.out));
public static Scanner sc = new Scanner(System.in);
/**
* 每月的天数
*/
public static int monthes[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
public static int maxd = 100000 + 15;
public static int INF = 0x3f3f3f3f;
public static int mod = (int) 1e9 + 7;
public static int[][] fx = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

public static void main(String[] args) throws Exception {

/**
* 正常处理代码
*/


closeAll();
}

public static int gcd(int a, int b) { // 不需要判断a和b的大小
while (b > 0) {
a %= b;
b ^= a;
a ^= b;
b ^= a;
}
return a;
}

public static int log(int x) { //log方法是以2为底,求x的对数.而java自带的log是以e为底的
return (int) (Math.log(x) / Math.log(2));
}

public static void cinInit() {
cin.wordChars('a', 'z');
cin.wordChars('A', 'Z');
cin.wordChars(128 + 32, 255);
cin.whitespaceChars(0, ' ');
cin.commentChar('/');
cin.quoteChar('"');
cin.quoteChar('\'');
cin.parseNumbers(); //可单独使用还原数字
}

public static int nextInt() throws Exception {
cin.nextToken();
return (int) cin.nval;
}

public static long nextLong() throws Exception {
cin.nextToken();
return (long) cin.nval;
}

public static double nextDouble() throws Exception {
cin.nextToken();
return cin.nval;
}

public static String nextString() throws Exception {
cin.nextToken();
return cin.sval;
}

public static void closeAll() throws Exception {
cout.close();
in.close();
out.close();
}
}

输入问题

总结输入输出的一些问题,主要是在既有数字又有字符串或都是字符串的情况下,如何读入。这里并没有用最基础的Scanner。

前数字后字符串(StreamTokenizer

先读入一个数字,然后再读入一个字符串。

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) throws Exception {

int n = nextInt();
String s = nextString();
System.out.println(n);
System.out.println(s);

closeAll();
}

输入和输出:

1
2
3
4
5
6
7
// in
10
abcdef

// out
10
abcdef

前数字后两行字符串,每行字符串都有由空格分割(BufferedReader

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) throws Exception {

int n = nextInt();
String s1 = in.readLine();
String s2 = in.readLine();
System.out.println(n);
System.out.println(s1);
System.out.println(s2);

closeAll();
}

输入输出:

1
2
3
4
5
6
7
8
// in
13
abc def g h
ab cd efg jl
// out
13
abc def g h
ab cd efg jl

技巧

统计二进制

统计一个数的二进制中1的个数。

1
2
3
4
int a = 123;
System.out.println(Integer.bitCount(a)); //6
long b = 123;
System.out.println(Long.bitCount(b)); //6

日期时间问题

日期格式参数

常用的:

参数 描述
yyyy 年。四个表示当年份只有二位数时,不足的用0补充。下同。
MM
dd
HH 小时
mm 分钟
ss
SSS 毫秒

日期和字符串的转化

记住两个方法:parse()、format()。前一个可以理解是用来解析字符串为Date;后一个可以理解为将Date转化为字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) throws Exception {

String s = "2022年3月15日";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); //提供解析模板,即按照什么样式进行解析
Date sd = sdf.parse(s);
System.out.println(sd);
SimpleDateFormat sdff = new SimpleDateFormat("yyyy-MM-dd"); //将日期格式化的样式
//sdff.setTimeZone(TimeZone.getTimeZone("UTC")); //设置时区
System.out.println(sdff.format(sd));


closeAll();
}

// 输出
Tue Mar 15 00:00:00 CST 2022
2022-03-15

两个时间间隔

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static void main(String[] args) throws Exception {
String startTime = "2013-7-13 13:14:23";
String endTime = "2021-7-13 13:14:24";
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d1 = format.parse(startTime);
Date d2 = format.parse(endTime);
long diff = Math.abs(d1.getTime() - d2.getTime());
System.out.println("相差 " + diff + " 毫秒");
long diffSeconds = diff / 1000 / 60; //秒
long diffMinutes = diff / (60 * 1000) % 60; //分钟
long diffHours = diff / (60 * 60 * 1000) % 24; //小时
long diffDays = diff / (24 * 60 * 60 * 1000); //天
System.out.print("两个时间相差:");
System.out.print(diffDays + " 天, ");
System.out.print(diffHours + " 小时, ");
System.out.print(diffMinutes + " 分钟, ");
System.out.println(diffSeconds + " 秒.");
System.out.println("相差 " + diffDays / 365 + " 年");
closeAll();
}

//输出
相差 252460801000 毫秒
两个时间相差:2922 天, 0 小时, 0 分钟, 1 秒.
相差 8

求给定日期信息

1
2
3
4
5
6
7
8
9
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒SSS毫秒");
System.out.println(sdf.format(date));
SimpleDateFormat sdf2 = new SimpleDateFormat("E 一年中的第w周、第D天 一个月中的第W周的周F 一天中的24制的第k小时(点)12制的第K小时(点)");
System.out.println(sdf2.format(date));

//输出
20211214171542407毫秒
星期二 一年中的第51周、第348天 一个月中的第3周的周2 一天中的24制的第17小时(点)12制的第5小时(点)

输出格式控制

设置宽度

设置输出占4个宽度的位置,不足的位置用0补充。

1
2
System.out.println(String.format("%04d",2));  //0002
System.out.println(String.format("%04d",12)); //0012

输出小数位数控制

String.format()

1
2
3
4
5
6
7
8
9
10
11
12
13
double a = 123.456789;
double b = 123.444444;
String sa = String.format("%.2f",a);
System.out.println(sa);
String sb = String.format("%.2f",b);
System.out.println(sb);

//输出
123.46
123.44

//简写
System.out.println(String.format("%.2f",a));

DecimalFormat的format方法

1
2
3
4
5
6
7
8
9
10
11
12
13
double a = 123.456789;
double b = 123.444444;
DecimalFormat dfa = new DecimalFormat("0.00");
System.out.println(dfa.format(a));
DecimalFormat dfb = new DecimalFormat("0.00");
System.out.println(dfb.format(b));

//输出
123.46
123.44

//简写
System.out.println(new DecimalFormat("0.00").format(a));

DecimalFormat 类主要靠 # 和 0 两种占位符号来指定数字长度。0 表示如果位数不足则以 0 填充,# 表示只要有可能就把数字拉上这个位置。如:

1
2
3
4
5
6
7
8
9
double a = 123.00;
DecimalFormat dfa = new DecimalFormat("#.##");
System.out.println(dfa.format(a));
DecimalFormat dfb = new DecimalFormat("0.00");
System.out.println(dfb.format(a));

//输出
123
123.00

BigDecimal的setScale方法(了解)

1
2
3
4
double f = 111231.5585;
BigDecimal bg = new BigDecimal(f);
double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue(); //setScale已经过时
System.out.println(f1);

NumberFormat的setMaximumFractionDigits方法(了解)

1
2
3
4
double f = 111231.5585;
NumberFormat nf = NumberFormat.getNumberInstance();
nf.setMaximumFractionDigits(2);
System.out.println(nf.format(f));

四舍五入

有三种方式:

String

1
2
System.out.println(String.format("%.0f",7.0/2)); //4
System.out.println(String.format("%.0f",7.0/3)); //2

Math

1
2
System.out.println(Math.round(7.0/2)); //4
System.out.println(Math.round(7.0/3)); //2

BigDecimal

1
2
3
4
5
6
7
BigDecimal bd1 = new BigDecimal(7.0/2);
BigDecimal bigDecimal1 = bd1.setScale(0, RoundingMode.HALF_UP); //保留0位,方式为常规四舍五入
System.out.println(bigDecimal1); //4

BigDecimal bd2 = new BigDecimal(7.0/3);
BigDecimal bigDecimal2 = bd2.setScale(0, RoundingMode.HALF_UP);
System.out.println(bigDecimal2); //2

进制转换

十进制转其他进制

一个重要的函数:Integer.toString(k,r) ,将十进制的数k转换为r进制的数。返回一个String。

1
2
3
4
5
6
7
8
9
10
11
int k = 17;
System.out.println(Integer.toBinaryString(k)); //转二进制
System.out.println(Integer.toOctalString(k)); //转八进制
System.out.println(Integer.toHexString(k)); //转十六进制

int r =2;
System.out.println(Integer.toString(k,r)); //转r进制
r=8;
System.out.println(Integer.toString(k,r)); //转r进制
r=16;
System.out.println(Integer.toString(k,r)); //转r进制

其他进制转换为十进制

函数:Integer.parseInt(str,r) ,将r进制的数字字符串str转换为十进制,并返回十进制的数。

1
2
3
4
5
6
7
8
System.out.println(Integer.parseInt("10001",2));
System.out.println(Integer.parseInt("21",8));
System.out.println(Integer.parseInt("11",16));

//输出结果
17
17
17

字符串与数字转换

数字转字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) throws Exception {

int n = 123456;
String s = String.valueOf(n);
s+='a';
String s1 = Integer.toString(n);
s1+='a';
System.out.println(s);
System.out.println(s1);

closeAll();
}

//输出
123456a
123456a

字符串转数字

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) throws Exception {

String s = "123465";
int n = Integer.valueOf(s);
n++;
System.out.println(n);

closeAll();
}

//输出
123466

自定义排序

自定义比较器

使用接口 Comparator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
public static void main(String[] args) throws Exception {

Integer[] a = {12, 56, 4, 56, 0, 1, 3, 2};
Integer[] b = {12, 56, 4, 56, 0, 1, 3, 2};
int n = a.length;

Arrays.sort(a, 0, n, new cmp2()); //升序
for (int i = 0; i < n; ++i) {
System.out.println(a[i]);
}
System.out.println("========================");
Arrays.sort(b, 0, n, new cmp()); //降序
for (int i = 0; i < n; ++i) {
System.out.println(b[i]);
}

closeAll();
}
//降序
static class cmp implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
}
//升序
static class cmp2 implements Comparator<Integer> {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}

//输出
0
1
2
3
4
12
56
56
========================
56
56
12
4
3
2
1
0

自定义类排序

自定义类也可以使用自定义比较器的方式进行排序,这里演示的是直接在类的内部写比较方法。使用接口 Comparable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Person implements Comparable<Person>{
private int id;

@Override
public String toString() {
return "Person{" +
"id=" + id +
'}';
}

@Override
public int compareTo(Person o) {
if(this.id<o.id) return 1;
else return -1;
}
}

类我并没有写完整,主要是看compareTo方法就行。之后也可以在集合中直接使用Collections.sort(List list)进行排序。例如:

1
2
List<Person> list = new ArrayList<>();
Collections.sort(list);

常用方法

判断字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String[] args) throws Exception {

char ch = 'a';
System.out.println(Character.isDigit(ch)); //是否为数字字符
System.out.println(Character.isLetter(ch)); //是否为字母
System.out.println(Character.isLowerCase(ch)); //是否为小写字符
System.out.println(Character.isUpperCase(ch)); //是否为大写字符
System.out.println(Character.isWhitespace(ch)); //是否为空白字符
System.out.println(Character.toUpperCase(ch)); //转化为大写字符
System.out.println(Character.toLowerCase(ch)); //转化为小写字符

closeAll();
}

// 输出
false
true
true
false
false
A
a

二分查找

数字必须是升序且,数字中没有重复元素。如果有重复元素,则找到的不一定是第一个。

1
2
3
4
5
6
7
8
public static void main(String[] args) throws Exception {

Integer[] a = {1,4,6,11,13,15,35,46};
System.out.println(Arrays.binarySearch(a,13)); //4
System.out.println(Arrays.binarySearch(a,0,8,13)); //4

closeAll();
}

大数处理

这里只说四种常见的运算,其他详情可见 蓝桥杯JAVA-6.大数(整数、小数)处理 。详情包含了求相反数、求模、求余、求幂次方、最大最小值、最大公约数等等。

构造

1
2
3
4
5
6
7
8
String s = sc.next(); //1561561561
BigInteger bs = new BigInteger(s);
System.out.println(bs); //1561561561


String s = sc.next(); //10000
BigInteger bs = new BigInteger(s,2); //将字符串数字当成2进制
System.out.println(bs); //16

整数

  • 相加
1
2
3
4
5
6
String s = "-23423432";
String ss = "23423433";
BigInteger bs = new BigInteger(s);
BigInteger bss = new BigInteger(ss);
BigInteger sad = bs.add(bss);
System.out.println(sad); //1
  • 相减
1
2
3
4
5
6
String s = "23423432";
String ss = "23423433";
BigInteger bs = new BigInteger(s);
BigInteger bss = new BigInteger(ss);
BigInteger sad = bss.subtract(bs); //bss-bs
System.out.println(sad); //1
  • 相乘
1
2
3
4
5
6
String s = "2";
String ss = "3";
BigInteger bs = new BigInteger(s);
BigInteger bss = new BigInteger(ss);
BigInteger sad = bss.multiply(bs);
System.out.println(sad);
  • 相除
1
2
3
4
5
6
String s = "3";
String ss = "7";
BigInteger bs = new BigInteger(s);
BigInteger bss = new BigInteger(ss);
BigInteger sad = bss.divide(bs); // bss/bs
System.out.println(sad); //2

小数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Scanner cin = new Scanner(System.in);
BigDecimal a,b;
a = cin.nextBigDecimal();
b = cin.nextBigDecimal();
System.out.println(a.add(b)); //加
System.out.println(a.subtract(b)); //减
System.out.println(a.multiply(b)); //乘
System.out.println(a.divide(b)); //除
System.out.println(a.remainder(b)); //求余
// a=7.3 b=3.2
10.5
4.1
23.36
2.28125
0.9

进制转换

  • 十进制转其他进制
1
2
3
4
5
6
7
8
9
10
11
12
13
String string1 = new BigInteger("20", 10).toString(2);
System.out.println("十进制的20转换成二进制是:"+string1);

String string2 = new BigInteger("20", 10).toString(8);
System.out.println("十进制的20转换成八进制是:"+string2);

String string3 = new BigInteger("20", 10).toString(16);
System.out.println("十进制的20转换成十六进制是:"+string3);

//out
十进制的20转换成二进制是:10100
十进制的20转换成八进制是:24
十进制的20转换成十六进制是:14
  • 其他进制转十进制
1
2
3
4
5
6
7
8
9
10
11
12
13
String string4 = new BigInteger("110", 2).toString(10);
System.out.println("二进制的110转换成十进制是:"+string4);

String string5 = new BigInteger("110", 8).toString(10);
System.out.println("八进制的110转换成十进制是:"+string5);

String string6 = new BigInteger("110", 16).toString(10);
System.out.println("十六进制的110转换成十进制是:"+string6);

//out
二进制的110转换成十进制是:6
八进制的110转换成十进制是:72
十六进制的110转换成十进制是:272