1. Java如何进行序列化
【解】Java中如果想要将某个对象序列化,该对象的类需要实现Serializable接口或者实现Externalizable接口。不同的是:实现Serializable接口无须实现任何方法,而实现Externalizable接口则必须为 writeExternal() 和 readExternal() 两个空方法提供实现。—— 在目标类实现了接口以后,就可以通过 ObjectOutputStream 将目标类对象进行序列化并输出了。
2. Exception,Error,RuntimeException在java异常处理中有什么不同
【解】Java中的异常分为 Error 和 Exception。其中Error一般指与虚拟机相关的错误,如系统崩溃、虚拟机错误、动态链接失败等,应用程序无法处理这些错误;Exception则是指应用程序本身可以处理的异常,它分为Checked Exception和RuntimeException —— Checked异常,也叫编译时异常,Java编译器强制要求我们必须对出现的这种异常进行catch处理,否则程序就不能编译通过;RuntimeException,即运行时异常,编译器不会检查运行时异常,我们也可以不处理,当出现这样的异常时,总是抛出由虚拟机接管。当然运行时异常也是可以catch的。
3. wait(), notify()和notifyAll()在使用的时候需要放在同步方法/代码块中吗?为什么?
【解】需要放在同步方法/同步代码块中,因为这三个方法必须由同步监视器对象来调用。在同步代码块中,同步监视器对象就是 synchronized() 括号中的对象;在同步方法中,同步监视器对象则是隐式的当前对象 this。—— 在调用wait()之前,当前线程已经通过synchronized获得了同步监视器的对象锁,调用了wait()以后,线程进入阻塞状态,并释放对象锁;其他线程获得了同步监视器的对象锁以后,就开始执行它的同步方法/代码块了,在同步方法/代码块中如果调用了notify(),则会唤醒在同步监视器对象上wait的任一线程,等剩余的代码执行完后,释放对象锁;被唤醒的线程尝试获取对象锁,获取到了以后线程继续向下执行。notifyAll()和notify()类似,只不过notifyAll()是唤醒在同步监视器对象上wait的所有线程,这些线程后续会争夺对象锁,谁得到对象锁谁继续执行。
4. 编程:给定两个字符串A,B(只包含26个英文字母),输出所有公共的最长子字符串(如果出现重复子串,则输出多次)
输入包括两行,每行为一个连续字符串(大小写敏感)
输出包括多行,每行为扫描到的最长公共子串,按照该子串在字符串A(即第一行输入字符串)中出现的先后次序输出
样例输入:
abcxyzabcrst
opqrstabc
样例输出:
abc
abc
rst
【解】见文《华为OJ2011-最长公共子串》与最长公共子序列一样,最长公共子串也可以采用动态规划(打表)进行求解。举个例子:X = bab,Y = caba。打表如下:
具体打表的方法是:
- 第一行、第一列初始化为 0;
- 对于其他的格子:
- 若对应的两个字符相等,格子的值设为左上角的值加 1。
- 若对应的两个字符不相等,直接置 0 。
- #include<iostream>
- #include<string>
- #include<vector>
- using namespace std;
- int main() {
- string X, Y;
- getline(cin, X);
- getline(cin, Y);
- int m = X.length();
- int n = Y.length();
- vector<vector<int> > table(m+1, vector<int>(n+1));
- int biggest = 0; // 记录表中的最大值
- vector<pair<int, int> > firstPos; // 记录子串开始的坐标
- for(int i=0; i<m+1; ++i)
- {
- for(int j=0; j<n+1; ++j)
- {
- if(i==0 || j==0) // 第一行和第一列置0
- table[i][j]=0;
- else if(X[i-1] == Y[j-1])
- {
- table[i][j] = table[i-1][j-1] + 1;
- if(table[i][j] > biggest)
- biggest = table[i][j];
- if(table[i][j] == 1)
- firstPos.push_back(make_pair(i, j));
- }
- else
- table[i][j] = 0;
- }
- }
- // 以下输出所有最长公共子串
- vector<pair<int,int> >::iterator it = firstPos.begin();
- for( ; it!=firstPos.end(); ++it)
- {
- int startX = it->first-1;
- int startY = it->second-1;
- if(X.substr(startX,biggest) == Y.substr(startY,biggest))
- cout << X.substr(startX, biggest) << endl;
- }
- }
5. 编程:在一个整数的数组中删除另外一个整数数组中的元素,并保留原数组的次序
输入包括两行:
1. 第一行是被删除的整数列表(记为列表A),每个整数之间使用空格分隔
2. 第二行是需要删除的整数列表(记为列表B),每个整数之间使用空格分隔
输出只有一行,即列表A中删除列表B元素后的整数列表,输出元素按照在列表A中的次序排列,每个整数之间使用空格分隔
样例输入:
1 2 3 4 5
2 4
样例输出:
1 3 5
【解】本题较简单,获取第一行时,用一个list保存;获取第二行时,将每个数从list中删除,最后输出即可。
- #include<iostream>
- #include<list>
- #include<string>
- #include<sstream>
- using namespace std;
- int main() {
- list<int> mylist;
- for(int i=0; i<2; ++i) {
- int n;
- string str;
- getline(cin, str);
- stringstream ss(str);
- while(!ss.eof()) {
- ss >> n;
- if(i==0)
- mylist.push_back(n);
- else
- mylist.erase(find(mylist.begin(),mylist.end(),n));
- }
- ss.clear();
- }
- list<int>::iterator it = mylist.begin();
- for( ;it!=mylist.end(); ++it) {
- cout << *it << " ";
- }
- }