算法理论实践大比拼

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,或者封装好的类库,血淋淋的教训

把它们养成一个习惯。形成一个良好的编程习惯能少走很多弯路


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值