一个算法产生的性能差异
demo下载:https://pan.baidu.com/s/1tMMWUFPw3ofELsA9QdPQgg 验证码:wq96
前言
- 题目更优(算法没有最优)答案是在技术群里某大佬发的
- 算法题题目很短,但是李大爷初次审题还是出错了
- 没有参考网站,纯属记录笔记
算法题目
- 说实话,第一次看确实看成了“字符串去重取长度”,甚至之后还重复看了好几遍才理解(丢人了  ̄□ ̄||)
代码实现
李大爷的实现方式
public static int lidaye(String str) {
// long t = System.nanoTime();
int maxInt = 0;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
int index = sb.indexOf(str.charAt(i) + "");
if(index != -1) {
sb = sb.delete(0,index+1);
}
sb.append(str.charAt(i));
maxInt = Math.max(maxInt,sb.length());
}
// System.out.println("test方法 =====================>> "+(System.nanoTime()-t)+"纳秒";
return maxInt;
}
某大神的实现方式
- 除了注释(计算耗时)的代码,基本上原封不动的 copy。
public static int test(String str) {
// long t = System.nanoTime();
int l = 0;
int res = 0;
Map<Character, Integer> map = new HashMap<>();
for (int i = 0; i < str.length(); i++) {
// 如果发现重复
if(map.containsKey(str.charAt(i))) {
l = Math.max(l,map.get(str.charAt(i))+1);
}
map.put(str.charAt(i),i);
res = Math.max(res,i-l+1);
}
// System.out.println("test方法 =====================>> "+(System.nanoTime()-t)+"纳秒";
return res;
}
差异说明:
李大爷:通过与临时字符串比较判断是否重复,通过临时字符串长度拿到最大值
某大神:通过Map集合匹配字符重复,通过集合中的值与当前下标换算出最大值
看结果
由于数据量会影响效率,所以开启计时,逐渐提升数据量
- 封装了一下,方便动态调整数据复制度(可跳过)
public static void run(int len, int pow) {
StringBuilder sb = new StringBuilder();
// 生成多个不重复字符
for (int i = 0; i < len; i++) {
sb.append((char) i);
}
// 字符重复多次幂
for (int j = 0; j < pow; j++) {
sb.append(sb.toString());
}
// 分别执行两个算法
test(sb.toString());
lidaye(sb.toString());
}
第一次
- 最长不重复长度:3,重复次数:4,总长度:12
public static void main(String[] args) {
run(3,2);
/**为了防止误差,执行了3次,结果如下:
* test方法 =====================>> 278001纳秒
* test方法 =====================>> 217500纳秒
* test方法 =====================>> 217200纳秒
* lidaye方法 =====================>> 28001纳秒
* lidaye方法 =====================>> 27701纳秒
* lidaye方法 =====================>> 29000纳秒
**/
}
第二次
- 最长不重复长度:3,重复次数:1048576,总长度:3145728
public static void main(String[] args) {
run(3,20);
/**为了防止误差,执行了3次,结果如下:
* test方法 =====================>> 118397300纳秒
* test方法 =====================>> 131224200纳秒
* test方法 =====================>> 96911799纳秒
* lidaye方法 =====================>> 105341200纳秒
* lidaye方法 =====================>> 89697600纳秒
* lidaye方法 =====================>> 113455701纳秒
**/
}
第三次
- 最长不重复长度:35,重复次数:4,总长度:140
public static void main(String[] args) {
run(35,2);
/**为了防止误差,执行了3次,结果如下:
* test方法 =====================>> 288301纳秒
* test方法 =====================>> 375101纳秒
* test方法 =====================>> 304600纳秒
* lidaye方法 =====================>> 154400纳秒
* lidaye方法 =====================>> 151800纳秒
* lidaye方法 =====================>> 151300纳秒
**/
}
第四次
- 最长不重复长度:200,重复次数:4,总长度:800
public static void main(String[] args) {
run(200,2);
/**为了防止误差,执行了3次,结果如下:
* test方法 =====================>> 2315801纳秒
* test方法 =====================>> 3041900纳秒
* test方法 =====================>> 807199纳秒
* lidaye方法 =====================>> 1336499纳秒
* lidaye方法 =====================>> 1446499纳秒
* lidaye方法 =====================>> 853801纳秒
**/
}
第五次
- 最长不重复长度:2000,重复次数:4,总长度:8000
public static void main(String[] args) {
run(2000,2);
/**为了防止误差,执行了3次,结果如下:
* test方法 =====================>> 5064101纳秒
* test方法 =====================>> 4235401纳秒
* test方法 =====================>> 3943100纳秒
* lidaye方法 =====================>> 11589000纳秒
* lidaye方法 =====================>> 7698000纳秒
* lidaye方法 =====================>> 7500999纳秒
**/
}
第六次(均衡调整效果)
- 最长不重复长度:300,重复次数:1024,总长度:512000
public static void main(String[] args) {
run(300,10);
/**为了防止误差,执行了3次,结果如下:
* test方法 =====================>> 33627100纳秒
* test方法 =====================>> 34181899纳秒
* test方法 =====================>> 45532799纳秒
* lidaye方法 =====================>> 38448300纳秒
* lidaye方法 =====================>> 36501901纳秒
* lidaye方法 =====================>> 39941200纳秒
**/
}
结论
- 重复次数对效率的影响不大,阈值大约在百万次(字符串长度少的情况下)
- 最大子长度(不重复算法)的阈值大约在800(重复次数少的情况下)
- 复杂程度在最长不重复长度在300重复次数1000以下的数据,字符串处理更快
李大爷的留言:
这算是李大爷第一次尝试接触算法题,过往一直以来没拿算法当回事。
想当初刚出来找工作有一家公司的面试官问:“觉得自己算法能力怎么样,平时有没有了解一些算法?”。答:“算法不是编程的基础吗!”,然后就回去等通知了。
在过去好几年里,李大爷一直不理解算法的定义,更别说认同算法对编程能带来帮助,而且在日常编程里也没遇到过比较难的算法。那为什么要练算法?可能就是提前做好对复杂业务需求的了解,等遇到类似的复杂业务就不至于“臣妾做不到”