踩坑记录

1
2
3
4
5
6
7
1. 3/2.0、1.0*3/2 都可以是1.5。
但是3/2*1.0不行,因为是先3/2强制取整变成1后再*1.0变为1.0。
所以要注意先后顺序。

2. 做题时,先看看能不能采用即时处理。
如果想着先全部处理完再输出很可能超时,但如果是一边处理判断一边输出则不容易超时
https://blog.csdn.net/RP123123123/article/details/122272967

可以用 int数组 代替 HashMap

常用于对字符串进行操作的算法题中,用来实现滑动窗口

目的: 提高效率,也更便于操作value

为什么可以这样做??

因为字符型ascii码最高就到128,所以只要创建一个占据128内存的数组就行,所占空间少。
其次字符型可以根据ascii码转成int,此时数组的下标所对应的字符(通过ascii码)就是key,下标对应的值就是value。例如a[65]=5
相当于 key=’A’,value=5

判断一个数是否是整数

1
2
3
4
// 判断s是否是整数
if(s == (int) s){
return 整数
}

判断素数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//判断num是否是素数
public boolean prime(int num){
// 1不是素数
if(num <= 1){
return false;
}
// 关键:i <= (int)Math.sqrt(num)
for(int i = 2; i <= (int)Math.sqrt(num); i++){
if(num % i == 0){
return false;
}
}
return true;
}

反转数字

1
2
3
4
5
6
7
8
9
//反转数字,用来判断是否是回文数
public int reverse(int num){
int ans = 0;
while(num > 0){
ans = ans*10 + (num%10);
num = num/10;
}
return ans;
}

浮点数取整

  • Math.ceil(double n); //对浮点数向上取整
  • Math.floor(double n); //对浮点数向下取整
  • Math.round(double n); //对浮点数四舍五入取整,不够准确。例如:-11.5 -> -11

利用大数类进行准确的四舍五入

1
2
//对10.7进行四舍五入取整
new BigDecimal("10.7").setScale(0,BigDecimal.ROUND_HALF_UP).intValue();

求最大公约数和最小公倍数

  • 最大公约数:比如说 15和12 的最大公约数 是 3
  • 最小公倍数:比如说 2 和 5 的最小公倍数 是 10
  • 最小公倍数 = a*b/a和b的最大公约数

最大公约数的实现 —— 辗转相除法(欧几里得算法)

1
2
3
4
5
1. c = a % b;
2. 若 c == 0 ,则 b 是 a和b 的最大公约数
3. 若 c != 0 ,则 令 a = b,b = c,再次执行第一步。

若要求最小公倍数,则在求出最大公约数后,用 最小公倍数 = a*b/a和b的最大公约数

最大公约数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public int GCD(int a,int b){      //求最大公约数
int t,c;
if(a < b){
t = a;
a = b;
b = t;
}
while(a%b != 0){
c = a % b;
a = b;
b = c;
}
return b;
}

最小公倍数

1
2
3
public int LCM(int a,int b){ //求最小公倍数
return a*b/GCD(a,b);
}

四舍五入

  • Math.ceil(double n); //对浮点数向上取整
  • Math.floor(double n); //对浮点数向下取整
  • Math.round(double n); //对浮点数四舍五入取整,不够准确。例如:-11.5 -> -11

利用大数类进行准确的四舍五入

1
2
//对10.7进行四舍五入取整
new BigDecimal("10.7").setScale(0,BigDecimal.ROUND_HALF_UP).intValue();

去重

  1. 用Set判断是否已经存在,若存在则不进行操作
1
2
3
4
5
6
7
8
public void distinct(int[] a){
Set<Integer> set = new HashSet<>();
for(int x : a){
if(set.add(x)){
System.out.println(x);
}
}
}
  1. 用Stream流
1
2
3
4
5
6
public void distinct(int[] a){
List<Integer> alist = Arrays.stream(a).distinct().collect(Collectors.toList());
for(int x : alist){
System.out.println(x);
}
}

快速输入和快速输出 —— BufferedReader和 BufferWriter

输入 —— BufferedReader

1
2
3
4
5
6
BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); 实例化
String/char/int s1 = in.read(); 读入一个字符。可单独读入空格或回车,回车会留下来被下次读取接收(吸收一个\n留下一个\r)
String s2 = in.readLine(); 读入一行,可读入空格。遇到回车结束,且回车会被舍弃,不会再被下次读取
String[] ss = in.readLine().split(" "); 将读入的一行字符串以空格分为字符串数组
……
in.close(); 关闭流

需要注意的是:

  • 在windows中按一下回车键,一共有两个字符 “\n\r”,而read()只能读取一个字符所以如要用read来达到吸收回车的目的,需要用两个read(); 如果用readLine()的话会将”\n\r”全部吸收 , 所以只需要一个readLine()来吸收回车。
  • 由于是字符型,用read()读取整型时,读取0会显示其as码48,读取9以上的数就会出问题了。所以我们应该用readLine()来接收,再利用Integer.parseInt()转化为整型

输出 —— BufferWriter

1
2
3
4
5
6
7
8
9
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out)); 实例化 
out.write(x);
out.write(" ");
out.write("\n");
out.write(x+"\n");
……
out.flush(); 在程序最后刷新一次即可,确保缓冲区的数据全部被输出
out.close(); 先刷新后关闭

需要注意的是:

  • write()不能直接输出int类型。因为BufferWriter是字符型流,直接用write(int a) 会输出其对应的ASCii码的字符 ,比如输出 65 会显示 A。可以通过write(String.valueOf(a)) 或 write(a+””)实现

记得在类声明后进行异常处理,throws IOException

利用 String.format() 格式化数据

原理类似于System.out.printf();

1
2
String s1 = String.format("%.2f\n",10.34567);
String s2 = String.format("你的名字是:%s\n","丁梓航");

求集合的交集、差集、并集

交集 —— retainAll()

1
2
3
4
se1.retainAll(set2)    //求set1和set2的交集,最终结果留在set1

set1 = {1,2,3,7},set2 = {1,3,8,9}
=> set1 = {1,3}

差集 —— removeAll()

1
2
3
4
se1.removeAll(set2)    //求set1和set2的差集,最终结果留在set1

set1 = {1,2,3,7},set2 = {1,3,8,9}
=> set1 = {2,7}

并集 —— addAll()

1
2
3
4
se1.addAll(set2)    //求set1和set2的并集,最终结果留在set1

set1 = {1,2,3,7},set2 = {1,3,8,9}
=> set1 = {1,2,3,7,8,9}