概览
这个部分就较为简单了,主要就是适应用 java 刷算法题目,若是面试,最好就用 java 来刷了。
先找到一个比较舒服的开始模板,然后逐渐适应 java,然后去使用和之前 c++平替的操作,若这个操作过于复杂,则可以记录下来。
若对于 c++这里的代码有一些比较相似的可以使用的可以列出。
这里说明一下,对于新拿到的一个 eclipse 软件,需要做哪些设置:eclipse的下载和 jdk的配置
- (若需要配置 JDK,否则略过)搜索 jre,选择 1.8 那个
- workspace 中选择 UTF-8
- compiler 选 1.8
- Editor 中的 Content Assist 写入
.abcdefghijklmnopqrstuvwxyz
(代码提示),再勾选Disable insertion triggers except "Enter
选项(取消按空格时自动填入代码) - 搜索 keys,设置 control+D copyLine
- 搜索 font,更换字体大概率没有
JetBrain
字体,选择Consolas
即可。
IO 总结
写了太多了,太乱了,这里总结:(前提为输入输出数据量大的情况,否则
stdio
即可)
关于标准输入输出:
Scanner scanner = new Scanner(new BufferedInputStream(System.in));
//Scanner scanner = new Scanner(System.in);
scanner.nextInt();
scanner.next();
scanner.nextDouble();
scanner.nextLine();
输出需要了解保留小数等特殊的情况
输入推荐:
- 如果需要更复杂的输入处理,使用
BufferedReader/StreamTokenizer
(大量数据的推荐)。
若使用 BufferedReader/StreamTokenizer
的注意事项:
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StreamTokenizer in = new StreamTokenizer(br);
in.nextToken();//每个都要加
//整数
in.nextToken();
int n = (int) in.nval;
//
in.nextToken();
double num = in.nval
//
in.nextToken();
String str = in.sval
//读取数组,ArrayList类似
in.nextToken();
int size = (int)in.nval; // 读取数组大小
int[] array = new int[size];
for (int i = 0; i < size; i++) {
in.nextToken();
array[i] = (int)in.nval;
}
//br.close()
读取自定义对象:
class Person {
String name;
int age;
static Person readPerson(StreamTokenizer in) throws Exception {
in.nextToken();
String name = in.sval; // 假设第一个是名字
in.nextToken();
int age = (int)in.nval; // 然后是年龄
return new Person(name, age);
}
Person(String name, int age) {
this.name = name;
this.age = age;
}
}
// 使用
in.nextToken();
int size = (int)in.nval; // 读取Person数组大小
ArrayList<Person> people = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
people.add(Person.readPerson(in));
}
输出推荐
- (若需要输出例如
个)推荐使用 PrintWriter
,API 更多,更易于使用
若使用 PrintWriter
的注意事项:
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
out.println(compute());
//还有更多API需要补充
//结束处理:(算法题也可以不处理)
out.flush();//这个不太清楚是每次输出都带还是最后带?
out.close();
IO
那么使用 BufferedReader
和 BufferedWriter
来处理数据可不可以做到不被时间卡住呢?
输入为
级别时,建议使用 BufferedReader
/StreamTokenizer
?BufferedReader
/String.split
呢?
输出为级别时,建议使用 BufferedWriter
?PrintWriter
稍慢
输入推荐:
- 如果数据格式简单,推荐使用
BufferedReader/String.split
。 - 如果需要更复杂的输入处理,使用
BufferedReader/StreamTokenizer
。
若使用 BufferedReader/String.split
的注意事项:(感觉挺麻烦的,而且相对较慢!)略
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
//读入int
String s=in.readLine();
int n=Integer.parseInt(s);
//若是一行读入多个,空格间隔,读入到ArrayList
ArrayList<String> list = new ArrayList<>();
String line = in.readLine();
String[] items = line.split("\\s+");
for (String item : items) {
list.add(item);
}
//in.close()
输出(若需要输出很多东西)推荐使用 PrintWriter
,API 更多,更易于使用
若使用 PrintWriter
实际上,对于 IO 的哪种方式好,还没有想好!平时使用一个较为简单的,能处理大量数据的即可(能做到不被时间卡住即可!)。
输出: BufferedWriter
vs PrintWriter
BufferedWriter
BufferedWriter
是一个用于缓冲的字符输出流,可以通过增加一个缓冲区来减少对底层输出的写操作。- 主要用于提高字符输出的效率。
- 不提供自动刷新功能,需要手动调用
flush()
确保所有数据被写出。
PrintWriter
PrintWriter
同样是字符输出流,更注重便捷性,提供了自动换行和自动刷新等功能。- 支持
print
和println
等方法,可以更方便地格式化输出。 - 适合需要频繁格式化输出的场景。
- 可以通过构造函数参数打开自动刷新功能(如在每次调用
println
后自动刷新)。
区别总结
BufferedWriter
注重效率,是处理大量字符输出时的好选择。PrintWriter
注重使用的便捷性,适合需要格式化输出的场景。- 在算法竞赛中,如果你需要频繁且复杂的格式化输出,
PrintWriter
可能更适合;否则,BufferedWriter
可能会更高效。
输入: BufferedReader
/ StreamTokenizer
vs BufferedReader
/ String.split
BufferedReader
with StreamTokenizer
StreamTokenizer
是一种工具类,用于解析输入流为一系列标记(tokens),适合处理结构化的输入数据。- 提供了一些内建的方法来解析各类标记(如数字、单词等)。
BufferedReader
with String.split
- 直接使用
BufferedReader
逐行读取输入,然后使用String.split()
方法来将读取的数据分割成数组。 - 更加灵活但需要自己管理数据转换。
区别总结
StreamTokenizer
提供了更高级的数据解析功能,更适合处理特定格式的数据,但相比手动解析略显繁琐。- 简单的行读取配合
String.split()
会更直接和灵活,适合大多数简单结构的数据。
推荐
- 输出: 如果你的算法题对输出格式有特定要求,且需要处理大量格式化输出,建议使用
PrintWriter
。否则,BufferedWriter
是一个高效的选择。 - 输入: 在算法题中,使用
BufferedReader
和行读取,然后用String.split()
在性能和灵活性上提供了一个平衡,是较为普遍的选择。StreamTokenizer
不太常用,除非掌握熟练,面临非常复杂的输入结构时才考虑使用。
在高效处理大数据的竞争环境中,选择合适的工具并了解其性能特征会对提升整体效率有显著帮助。
//对于大数据比较好,那就用这个
Scanner scanner = new Scanner(new BufferedInputStream(System.in));
OR
//Scanner scanner = new Scanner(System.in);
接收数据(有新的东西补充即可)
scanner.nextInt();
scanner.next();
scanner.nextDouble();
scanner.nextLine();
需要寻找一个尽量 FAST_IO
的方式!(适用于数据量很大的情况)
需要抛出 throws IOException
// 创建一个 BufferedReader,用于从标准输入流(System.in)读取数据
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
// 创建一个 StreamTokenizer,用于将输入流解析为标记(tokens)
StreamTokenizer in = new StreamTokenizer(br);
// 创建一个 PrintWriter,用于向标准输出(System.out)写入数据(结果)
PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
//结束位置->
// 刷新输出流,确保所有数据都被写出
out.flush();
// 关闭流,进行资源释放
out.close();
br.close();
若要读入(这里的读入还是相对麻烦的!)
//读入一个int
in.nextToken();
int n = (int) in.nval;
所以在数据量不大的情况下,尽量用 Scanner
即可。
普通数组
和 c++很像
int[] array = new int[5]; // 创建一个长度为5的int数组,初始值为0
//复制整个数组:
int[] copy = array.clone();
Arrays.fill(array, value);
int[][] twoDimArray = new int[3][2]; // 创建一个3x2的二维数组
//0 1 0 0 0 ->
//[0, 1, 0, 0, 0]
String arrayString = Arrays.toString(array);
vector
对于 c++的 vector
,在 java 中用 ArrayList
替代即可。
//vector<int> a(10,0);
ArrayList<Integer> a=new ArrayList<>(Collections.nCopies(10, 0));
//a[0]=1;
a.set(0, 1);
//快速遍历方式
a.forEachprintln;
//vector<vector<int>> a(26);
ArrayList<ArrayList<Integer>> a = new ArrayList<>(26);
for(int i=0;i<26;i++)a.add(new ArrayList<>());
//这种方式不推荐,所有数组都引用的同一个对象!会出问题!
//ArrayList<ArrayList<Integer>> a = new ArrayList<>(Collections.nCopies(26, new ArrayList<>()));
// 向指定位置插入元素
a.get(0).add(1); //a[0].push_back(1);
a.get(0).add(2);
// 获取指定位置的元素
int element = a.get(0).get(1);//a[0][1];
对于排序
- 推荐
Collections.sort
和lambda
方式进行排序(总之,我认为越简单越好!) a.sort((x,y)->x-y);
深得我心
//sort(a.begin(),a.end());
a.sort(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;//反过来则为降序排序
}
});
//lambda<->等价
a.sort((x,y)->x-y);
Collections.sort(a,new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
二分:
//int x=lower_bound(ans.all(),k)-ans.begin();
int x=Collections.binarySearch(ans, k);
String
//s[i]
s.charAt(i);