• LeetCode


    题目

    URL:https://leetcode.com/problems/longest-substring-without-repeating-characters

     

    解法

    一、Hash by HashMap

    核心思想是,判断字符是否在 HashMap 中,如果是,那么计算当前不重复字串的长度,和之前不重复子串的长度比较并决定是否更新,之后更新在 HashMap 该字符的下标,如果否,将字符加入 HashMap 中。遍历到最后再次计算所有不重复最长子串,因为最后子串也是最长的。

        public int lengthOfLongestSubstring(String s) {
            char[] c = s.toCharArray();
            HashMap<Character, Integer> map = new HashMap<>();
            int max = 0, noRepeatingStart = 0;
            for (int i = 0; i < c.length; i++) {
                if (map.containsKey(c[i])) {
                    max = i - noRepeatingStart > max ? i - noRepeatingStart : max;
                    noRepeatingStart = map.get(c[i]) + 1 > noRepeatingStart ? map.get(c[i]) + 1 : noRepeatingStart;
                    map.replace(c[i], i);
                } else {
                    map.put(c[i], i);
                }
            }
            return max > c.length - noRepeatingStart ? max : c.length - noRepeatingStart;
        }

    Hash by HashMap,时间复杂度O(n),运行时间约为 54 ms。

    二、Hash by Array(Best Solution)

    参考:https://discuss.leetcode.com/topic/33361/java-runtime-4ms/11

    其实没有必要用 HashMap 映射,比较耗时。这里因为只有 256 个 ASCII 字符,所以可以直接 Hash 到数组上。

    start 记录不重复子串初始位置, end 记录不重复子串终止位置,max 记录最长长度。chars 映射数组表示字符上一次出现的下标,值为 0 表示未出现。遍历字符时,当发现字符出现在不重复子串之后,计算当前不重复子串长度,比较之前不重复子串长度决定是否更新不重复子串最长长度,之后在 chars 映射数组上更新字符的下标(这里为从 1 作为起始下标)。遍历到最后再次计算所有不重复最长子串,因为最后子串也是最长的。

        public int lengthOfLongestSubstring(String s) {
            if (s.length() == 0) return 0;
            int start = 1, end = 1, max = 0;
            int[] chars = new int[256];
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                if (chars[c - ' '] >= start) {
                    max = max > end - start ? max : end - start + 1;
                    start = chars[c - ' '] + 1;
                }
                end = chars[c - ' '] = i + 1;
            }
            max = max > end - start ? max : end - start + 1;
            return max;
        }

    Hash by Array,时间复杂度O(n),运行时间约为 54 ms。

    总结

    同样利用 Hash 技术,手工的 Hash by Array 比系统自带的 Hash by HashMap 快了 25% 左右。能简单 Hash 的还是手工 Hash 比较好。

    其实我也不清楚到底哪种算法比较好,我有的时候会觉得 Hash by HashMap 比较科学。因为它有利于程序设计,编写代码者只需要考虑如何组织 Hash,并不需要设计 Hash,此外,手工 Hash by Array 很容易因为下标的问题产生错误。

    不管怎么样,HashMap 的原理还是有必要了解的,不然很容易产生性能问题。

  • 相关阅读:
    Druid数据库密码加密
    jenkins 构建时不能自动结束的问题
    4、TypeScript 类
    3、TypeScript 函数
    2、Typescript 中的数据类型
    1、TypeScript安装、开发工具
    Markdown 基本格式
    解决邮箱下载下来的word打不开的问题
    winform在禁用控件上显示工具提示
    日常问题集
  • 原文地址:https://www.cnblogs.com/Piers/p/6980359.html
Copyright © 2020-2023  润新知