2014年4月份,参加了金山网络的笔试题,其中有一道题有点意思。
题目:
两个字符串或字符数组的字符种类,个数相同,则判断两个字符串或者字符数组相等。不考虑字符出现的顺序。
如str1 = “aaab”
str2 = "aaba"
则str1跟str2相等
编写一个判断两个字符串或者字符数组是否相同。
看到这里是否觉得题目很简单?当然这里讲的是理论跟实践的结果比对下。
思路1:先判断长度,若相等,将str1与str2排序下,遍历str1或str2,若有字符不相等,则两个字符串不相等。
分析:排序算法若采用快排,则实践复杂度为平均时间复杂度log2(n)*n。时间呈线性增长
思路2:先判断长度,若相等,则遍历str1,str2,存储str1与str2中的字符出现的个数,判断字符的种类,出现的个数是否一致。
分析:这里我们用hashmap来存储str1与str2中的字符,时间复杂度为O(1),遍历hashmap判断
从理论上将,思路2比思路1要好,时间复杂度思路2要小一点。实践一下,真的是这样吗?你真的确定思路2运算时间比思路1要快?那就让我们时间下吧。
为了更好地突显思路2的优势,往txt中存放着10W个随机出现的字符,存储在str1,str2数组中。上代码
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Array;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class Main {
public static HashMap<Character, Integer> map1=new HashMap<Character, Integer>();
public static HashMap<Character, Integer> map2=new HashMap<Character, Integer>();
public static char ch1[];
public static char ch2[];
public static void main(String[] args) {
long startTime=System.currentTimeMillis(); //获取开始时间
ch1 = readToString("E:/javacode/字符串对比/string100000A.txt");
ch2 = ch1.clone();
if(judge1()){
System.out.println("ture");
}else{
System.out.println("false");
}
long endTime=System.currentTimeMillis(); //获取结束时间
System.out.println(endTime-startTime);
}
public static boolean judge(){
Arrays.sort(ch1);
Arrays.sort(ch2);
for(int i=0; i<ch1.length; ++i){
if(ch1[i] != ch2[i]){
return false;
}
}
return true;
}
public static void initHashmap(char ch1[],char ch2[]){
for(int i=0; i<ch1.length; ++i){
Integer count = map1.get(ch1[i]);
if(count == null){
count = 0;
}
map1.put(ch1[i], count+1);
}
map2 = (HashMap<Character, Integer>) map1.clone();
}
public static boolean judge1(){
initHashmap(ch1, ch2);
Iterator iter = map1.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry1 = (Map.Entry) iter.next();
Character key = (Character) entry1.getKey();
Integer count1 = map1.get(key);
Integer count2 = map2.get(key);
if(count1 != count2){
return false;
}
}
return true;
}
public static char[] readToString(String fileName) {
File file = new File(fileName);
Long filelength = file.length();
byte[] filecontent = new byte[filelength.intValue()];
try {
FileInputStream in = new FileInputStream(file);
in.read(filecontent);
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Charset cs = Charset.forName ("UTF-8");
ByteBuffer bb = ByteBuffer.allocate (filecontent.length);
bb.put (filecontent);
bb.flip ();
CharBuffer cb = cs.decode (bb);
return cb.array();
// return new String(filecontent, encoding);
}
}
运行下,
思路一:
ture
6
思路二:
ture
18
是的,你没看错,思路一的运行时间为6ms,思路二的运行时间为18ms。
总结下:
理论跟实践总是有差距,但这并不代表着我上面思路二的实践是正确的。
平时编程时注意以下几个习惯
1、查找排序号的数组时,记得用二分。
2、乱序的数组排序时,记得用快排。
3、千万不要挑战STL,或者封装好的类库,血淋淋的教训
把它们养成一个习惯。形成一个良好的编程习惯能少走很多弯路