一个算法产生的性能差异-无重复字符的最长子串

一个算法产生的性能差异


算法练习网站

demo下载:https://pan.baidu.com/s/1tMMWUFPw3ofELsA9QdPQgg 验证码:wq96

前言

  1. 题目更优(算法没有最优)答案是在技术群里某大佬发的
  2. 算法题题目很短,但是李大爷初次审题还是出错了
  3. 没有参考网站,纯属记录笔记

算法题目

  • 说实话,第一次看确实看成了“字符串去重取长度”,甚至之后还重复看了好几遍才理解(丢人了  ̄□ ̄||)

算法题目

代码实现

李大爷的实现方式

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纳秒
     **/
}

结论

  1. 重复次数对效率的影响不大,阈值大约在百万次(字符串长度少的情况下)
  2. 最大子长度(不重复算法)的阈值大约在800(重复次数少的情况下)
  3. 复杂程度在最长不重复长度在300重复次数1000以下的数据,字符串处理更快

李大爷的留言:
  这算是李大爷第一次尝试接触算法题,过往一直以来没拿算法当回事。
  想当初刚出来找工作有一家公司的面试官问:“觉得自己算法能力怎么样,平时有没有了解一些算法?”。答:“算法不是编程的基础吗!”,然后就回去等通知了。
  在过去好几年里,李大爷一直不理解算法的定义,更别说认同算法对编程能带来帮助,而且在日常编程里也没遇到过比较难的算法。那为什么要练算法?可能就是提前做好对复杂业务需求的了解,等遇到类似的复杂业务就不至于“臣妾做不到”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值