用java以正确的姿势刷CSP
来源:互联网 发布:windows一直在准备配置 编辑:程序博客网 时间:2024/05/19 09:17
许多程序算法考试中,用java是个不错的选择,它几乎实现了所有c++能实现的,所以越来越受Acmer的欢迎。总结一下用到的一些技巧和方法。更多关于csp的可参考海岛blog|皮卡丘
1. 输出
规格化的输出
System.out.printf(); // 与C中的printf用法类似.
System.out.printf(“%d %10.5f\n”, a, b); // 输入b为字宽为10,右对齐,保留小数点后5位,四舍五入.
// 这里0指一位数字,#指除0以外的数字(如果是0,则不显示),四舍五入.
DecimalFormatDecimalFormat fd = new DecimalFormat("#.00#");DecimalFormat gd = new DecimalFormat("0.000");System.out.println("x =" + fd.format(x));System.out.println("x =" + gd.format(x));
BigInteger和BigDecimal
包括函数:add, subtract, multiply,divide, mod, compareTo等,其中加减乘除模都要求是BigInteger(BigDecimal)和BigInteger(BigDecimal)之间的运算,所以需要把int(double)类型转换为BigInteger(BigDecimal),用函数BigInteger.valueOf().
compareTo:根据该数值是小于、等于、或大于 val 返回 -1、0 或 1;
equals:判断两数是否相等,也可以用compareTo来代替;
min,max:取两个数的较小、大者;
BigInteger add(BigInteger other) BigInteger subtract(BigInteger other) BigInteger multiply(BigInteger other) BigInteger divide(BigInteger other) BigInteger mod(BigInteger other) int compareTo(BigInteger other) static BigInteger valueOf(long x)
输出大数字时直接使用 System.out.println(a) 即可。
2. 输入
读一个字符串:String s = cin.next(); 相当于 scanf(“%s”, s); 或 cin >> s;//注意是字符串而不是单个字符
3. Arrays.sort() 跟 Collection.sort()
一种是使用Comparable接口:让待排序对象所在的类实现Comparable接口,并重写Comparable接口中的compareTo()方法,缺点是只能按照一种规则排序。
(1)class Person implements Comparable{
(2)//重写该类的compareTo()方法,使其按照从小到大顺序排序
@Override public int compareTo(Person o) { return age-o.age; }
另一种方式是使用Comparator接口:编写多个排序方式类实现Comparator接口,并重写新Comparator接口中的compare()方法,在调用Arrays的sort()时将排序类对象作为参数传入:public static void sort(T[] a,Comparatorc),根据指定比较器产生的顺序对指定对象数组进行排序。数组中的所有元素都必须是通过指定比较器可相互比较的(也就是说,对于数组中的任何 e1 和 e2 元素而言,c.compare(e1, e2) 不得抛出 ClassCastException)。
//创建SortByNumber对象,将其作为参数传入
Arrays.sort(persons,sortByNumber)方法中
SortByNumber sortByNumber = new SortByNumber(); Arrays.sort(persons,sortByNumber);
//按照学号由低到高排列,创建SortByNumber类,该类实现Comparator,重写该接口的compare()
class SortByNumber implements Comparator<student>{ //重写该接口的compare()使其按照学号由小到大排序(前者减去后者) @Override public int compare(Student o1, Student o2) { return o1.getNumber()-o2.getNumber(); }}
//按照分数由高到低排列,创建SortByScore类,该类实现Comparator,重写该接口的compare()
class SortByScore implements Comparator<student>{ //重写该接口的compare()使其按照分数由高到低排序(后者减去前者) @Override public int compare(Student o1, Student o2) { return o2.getScore()-o1.getScore(); }
优点是可以按照多种方式排序,你要按照什么方式排序,就创建一个实现Comparator接口的排序方式类,然后将该排序类的对象传入到Arrays.sort(待排序对象,该排序方式类的对象)
我喜欢用第二种方法,而且是直接new接口(),z在方法参数中自己实现,当然如果主要的逻辑在排序这里,用第一种方法其实才是不错的选择。
4. Arrays. binarySearch()
注:此法为二分搜索法,故查询前需要用sort()方法将数组排序,如果数组没有排序,则结果是不确定的.
substring()方法 是左闭右开的
⑴ .binarySearch(object[ ], object key);
如果key在数组中,则返回搜索值的索引;否则返回-1或者”-“(插入点)。插入点是索引键将要插入数组的那一点,即第一个大于该键的元素索引。这个插入点是什么呢,刚开始我也有点困惑,不过当我看了源代码以后,就明白了,至于为什么这么做,(⊙o⊙)…,谁知道?
1.不存在时由1开始计数;
2.存在时由0开始计数。
⑵.binarySearch(object[ ], int fromIndex, int endIndex, object key);
如果要搜索的元素key在指定的范围内,则返回搜索键的索引;否则返回-1或者”-“(插入点)。
eg:
1.该搜索键在范围内,但不在数组中,由1开始计数;
2.该搜索键在范围内,且在数组中,由0开始计数;
3.该搜索键不在范围内,且小于范围内元素,由1开始计数;
4.该搜索键不在范围内,且大于范围内元素,返回-(endIndex + 1);(特列)
对于这一点,太狠,我记不住。用的大多是找到的,找不到的返回负数来判断即可。
5. Arrays.fill()
public static void fill(Object[] a, int fromIndex, int toIndex, Object val)
//将指定的 Object 引用分配给指定 Object 数组指定范围中的每个元素。填充的范围从索引 fromIndex(包括)一直到索引 toIndex(不包括)。(如果 fromIndex==toIndex,则填充范围为空。)
抛出:
IllegalArgumentException - 如果 fromIndex > toIndex
ArrayIndexOutOfBoundsException - 如果 fromIndex < 0 或 toIndex > a.length
ArrayStoreException - 如果指定值不是可存储在指定数组中的运行时类型.
Arrays.fill( a1, value );
a1是一个数组变量,value是一个a1中元素数据类型的值,作用:填充a1数组中的每个元素都是value
6. 进制
java中进行二进制,八进制,十六进制,十进制间进行相互转换
Integer.toHexString(int i) //十进制转成十六进制Integer.toOctalString(int i) //十进制转成八进制Integer.toBinaryString(int i) //十进制转成二进制Integer.valueOf("FFFF",16).toString() //十六进制转成十进制Integer.valueOf("876",8).toString() //八进制转成十进制Integer.valueOf("0101",2).toString() //二进制转十进制String st = Integer.toString(num, base); // 把num当做10进制的数转成base进制的st(base <= 35).
使用cin.toString(2);//将它转换成2进制表示的字符串
还有一种通用的方法。
parseInt(String s, int radix)
至于转换成二进制或其他进制,Java API提供了方便函数,用eclipse 可以查看到。总结一点,toXXX这种是将十进制转换为其他 valueOf 是将其他转为十进制。 好像看起来都行嘛,有些是不是有点重复了,我是这么认为的。
还有一种转换就是,包装型与普通的转换,比如包装—>普通。To.shortValue().反过来的话用构造方法赋值即可。
- 变量的定义和使用
- 如果是全局使用的栈,队列,输入对象等,尽量定义在全局里面,因为csp考试是单点测试的,而且可以方便传参,还有个好处是将空间分配到堆上面,不容易溢出。
int[] a = new int[100]; //默认用0填充 Boolean [] b = new Boolean[12];//默认用false填充
8. 正则表达式
Java 中的正则表达式java.util.regex包中,在从母串里取出子串的题可以用到,方便一些,否则就只能自己判断了,实属麻烦,所以总结了一些。参考https://www.cnblogs.com/Mustr/p/6060242.html
(1) 预定义符号介绍
(2) 数量词
(3) 边界匹配符号说明
(4) 其他符号
()的使用 – 组
() 将 () 之间括起来的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域,这个元字符在字符串提取的时候非常有用。捕获组可以通过从左到右计算其开括号来编号。
(\d) 第一组
((A)(B(C))) 第一组 ((A)(B(C))) 第二组 (A) 第三组(B(C)) 第四组(C)
常用的操作:
- 匹配
String matches()方法。用规则匹配整个字符串,只要有一处不符合规则,就匹配结束,返回false。
public static void checkQQ(){ String qq = "123a45664"; String regex = "[1-9]\\d{4,14}"; boolean flag = qq.matches(regex); if(flag) System.out.println(qq+"...is ok"); else System.out.println(qq+"... 不合法"); }
/* 匹配 手机号段只有 13xxx 15xxx 18xxxx */ public static void checkTel() { String tel = "16900001111"; String telReg = "1[358]\\d{9}"; System.out.println(tel.matches(telReg)); } //不合法
2 .切割
public static void splitDemo() { String str = "avg bb geig glsd abc"; String reg = "[ ,]+";//按照多个空格或者逗号来进行切割 String[] arr = str.split(reg); System.out.println(arr.length); for(String s : arr) { System.out.println(s); } }
public static void splitDemo() { String str = "erkktyqqquizzzzzo"; String reg ="(.)\\1+";//按照叠词来进行切割 //可以将规则封装成一个组。用()完成。组的出现都有编号。 //从1开始。 想要使用已有的组可以通过 \n(n就是组的编号)的形式来获取。 String[] arr = str.split(reg); System.out.println(arr.length); for(String s : arr) { System.out.println(s); } } // er,ty,ui,o
3 .替换
public static void replaceAllDemo() { String str = "wer1389980000ty1234564uiod234345675f";//将字符串中的数字替换成#。 str = str.replaceAll("\\d{5,}","#"); System.out.println(str); } // wer#ty#uio#f
//组选择public static void replaceAllDemo() { String str1 = "erkktyqqquizzzzzo";//将叠词替换成$. //将重叠的字符替换成单个字母。zzzz->z str = str.replaceAll("(.)\\1+","$1"); System.out.println(str); } // erktyquizo
4 . 从某个字符串中取某个字符串
操作步骤:
1,将正则表达式封装成对象。
2,让正则对象和要操作的字符串相关联。
3,关联后,获取正则匹配引擎。
4,通过引擎对符合规则的子串进行操作,比如取出。
public static void getDemo() { String str = "java shi wo zui xi huan de bian cheng yu yan "; System.out.println(str); String reg = "\\b[a-z]{3}\\b";//匹配只有三个字母的单词 //将规则封装成对象。 Pattern p = Pattern.compile(reg); //让正则对象和要作用的字符串相关联。获取匹配器对象。 Matcher m = p.matcher(str); //System.out.println(m.matches());//其实String类中的matches方法。用的就是Pattern和Matcher对象来完成的。 //只不过被String的方法封装后,用起来较为简单。但是功能却单一。 // boolean b = m.find();//将规则作用到字符串上,并进行符合规则的子串查找。 // System.out.println(b); // System.out.println(m.group());//用于获取匹配后结果。 while(m.find()) { System.out.println(m.group()); System.out.println(m.start()+"...."+m.end()); // start() 字符的开始下标(包含) //end() 字符的结束下标(不包含) } }
9.常用模板
Dfs bfs
参考博客:http://blog.csdn.net/qq_24486393/article/details/50270481
//bfs dfs 递归跟非递归package com.ccf.test2;import java.util.LinkedList; import java.util.Queue; import java.util.Stack;/** * @author hulichao * @date Dec 1, 2017 * @version 1.0 * */public class Graph { private int number = 9; private boolean[] flag; private String[] vertexs = { "A", "B", "C", "D", "E", "F", "G", "H", "I" }; private int[][] edges = { { 0, 1, 0, 0, 0, 1, 1, 0, 0 }, { 1, 0, 1, 0, 0, 0, 1, 0, 1 }, { 0, 1, 0, 1, 0, 0, 0, 0, 1 }, { 0, 0, 1, 0, 1, 0, 1, 1, 1 }, { 0, 0, 0, 1, 0, 1, 0, 1, 0 }, { 1, 0, 0, 0, 1, 0, 1, 0, 0 }, { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, { 0, 0, 0, 1, 1, 0, 1, 0, 0 }, { 0, 1, 1, 1, 0, 0, 0, 0, 0 } }; void DFSTraverse() { flag = new boolean[number]; for (int i = 0; i < number; i++) { if (flag[i] == false) {// 当前顶点没有被访问 DFS(i); } } } void DFS(int i) { flag[i] = true;// 第i个顶点被访问 System.out.print(vertexs[i] + " "); for (int j = 0; j < number; j++) { if (flag[j] == false && edges[i][j] == 1) { DFS(j); } } } void DFS_Map(){ flag = new boolean[number]; Stack<Integer> stack =new Stack<Integer>(); for(int i=0;i<number;i++){ if(flag[i]==false){ flag[i]=true; System.out.print(vertexs[i]+" "); stack.push(i); } while(!stack.isEmpty()){ int k = stack.pop(); for(int j=0;j<number;j++){ if(edges[k][j]==1&&flag[j]==false){ flag[j]=true; System.out.print(vertexs[j]+" "); stack.push(j); break; } } } } } void BFS_Map(){ flag = new boolean[number]; Queue<Integer> queue = new LinkedList<Integer>(); for(int i=0;i<number;i++){ if(flag[i]==false){ flag[i]=true; System.out.print(vertexs[i]+" "); queue.add(i); while(!queue.isEmpty()){ int k=queue.poll(); for(int j=0;j<number;j++){ if(edges[k][j]==1&&flag[j]==false){ flag[j] = true; System.out.print(vertexs[j]+" "); queue.add(j);//注意没有 break; } } } } } } public static void main(String[] args) { Graph graph = new Graph(); System.out.println("DFS递归:"); graph.DFSTraverse(); System.out.println(); System.out.println("DFS非递归:"); graph.DFS_Map(); System.out.println(); System.out.println("BFS非递归:"); graph.BFS_Map(); } }
全排列,递归
参考:http://blog.csdn.net/randyjiawenjie/article/details/6313729
package com.ccf.test2;/** * @author hulichao * @date Dec 1, 2017 * @version 1.0 * */public class RecursionPermutation { public static void permutate(String input){ if(input == null) throw new IllegalArgumentException(); char[] data = input.toCharArray(); permutate(data, 0); } public static void permutate(char[] data, int begin){ int length = data.length; if(begin == length) System.out.println(data); for(int i = begin ; i < length; i++) { if(isUnique(data, begin, i)){ swap(data, begin, i); permutate(data, begin + 1); swap(data, begin, i); } } } private static boolean isUnique(char[] data, int begin, int end){ for(int i = begin; i < end; i++) if(data[i] == data[end]) return false; return true; } private static void swap(char[] data, int left, int right) { char temp = data[left]; data[left] = data[right]; data[right] = temp; } public static void main(String... args){ RecursionPermutation.permutate("aac"); }}
声明:许多代码片段,因为参考当时自己在编辑器运行过,后面没记住网址,如有必要,请联系我!
- 用java以正确的姿势刷CSP
- 新手学Android之如何以正确的姿势debug
- 如何以“正确的姿势”阅读开源软件代码
- 以正确的姿势实现一棵JavaScript菜单树
- 图带逛:以正确的姿势查看知乎图片
- HDU 5047:JAVA输入输出的正确姿势
- Java getInstance() 单例的正确姿势
- java读取文件的正确姿势
- Java单例的正确使用姿势
- 【Java】jdk8 Optional 的正确姿势
- 使用 Java 8 Optional 的正确姿势
- 【Java】jdk8 Optional 的正确姿势
- 使用java 8 Optional 的正确姿势
- Java 同步锁的正确姿势
- Java 8 Optional的正确姿势
- 用正确的姿势使用volley
- 用VSCode写python的正确姿势
- 用SLF4J输出log的正确姿势
- C语言文件读写操作总结
- 利用weka.jar算法改进
- 20个高级Java面试题汇总
- Chrome隐私设置错误,您的链接不是私密连接
- LDA and QDA
- 用java以正确的姿势刷CSP
- python入门(2)
- C++关键字之explicit
- 真实实践中的MeritMS与Project Wise的校审流程对比
- 超详细的系统时钟和定时器原理解析
- 【拜小白opencv】43-形态学滤波——综合示例【腐蚀、膨胀、开运算、闭运算、顶帽、黑帽 形态学梯度、内部梯度、外部梯度、X方向梯度、Y方向梯度】
- Bzoj3998 弦论
- JVM--详解类加载机制
- Android混淆机制