• 判定字符是否唯一的面试题想到


    题目出处 力扣(LeetCode) https://leetcode-cn.com/problems/is-unique-lcci/

    实现一个算法,确定一个字符串 s 的所有字符是否全都不同。
    
    示例 1:
    
    输入: s = "leetcode"
    输出: false 
    示例 2:
    
    输入: s = "abc"
    输出: true
    限制:
    
    0 <= len(s) <= 100
    如果你不使用额外的数据结构,会很加分。
    

    就是这么简单一道题,居然看到灰常多的解法。虽然题目提示尽量不用额外的数据机构,但实际开发中,内置的数据结构除了内存稍微多了那么一点点,我觉得并没什么不妥。但作为面试题来做就按出题者的意图来做吧。

    java8 stream

    执行效率2ms 内存36.4左右 一行代码就搞定

    public static boolean isUnique(String astr) {
            return astr.chars().distinct().count() == astr.length();
        }
    

    set去重一

    执行效率0ms 内存36.4左右

    public boolean isUnique(String astr) {
            HashSet<Character> set = new HashSet<>();
            for(char c : astr.toCharArray()){
                if(!set.add(c)) {
                    return false;
                }
            }
            return true;
        }
    

    set去重二

    执行效率0ms 内存36.1左右

    public boolean isUnique(String astr) {
            HashSet<Character> hashSet = new HashSet<>();
            for (int i = 0; i < astr.length(); i++) {
                hashSet.add(astr.charAt(i));
            }
            return hashSet.size() == astr.length() ;
        }
    

    set去重三

    执行效率0ms 内存36.1左右

    public boolean isUnique(String astr) {
            HashSet<Character> set = new HashSet<>();
            for (int i = 0; i < astr.length(); i++) {
                if(!set.add(astr.charAt(i))) {
                    return false;
                }
            }
            return true;
        }
    

    set去重一、二大致相同,但第一种方法中astr.toCharArray()方法自然是多用了内存。而去重三和二比的话在某些情况有不同之处的

    传统遍历一

    执行效率0ms 内存36.2

    ## 当前字符是否在  是否包含在后续的字符中
    public boolean isUnique(String astr) {
            for(int i=0;i<astr.length();i++){
               if(astr.substring(i+1).contains(String.valueOf( astr.charAt(i) )) )
                   return false;
            }
            return true;
        }
    

    传统遍历二

    执行效率0ms 内存36.1

    ## 当前字符,从后往前找索引是否一致
     public boolean isUnique3(String astr) {
            for(int i=0;i<astr.length();i++){
                if(astr.lastIndexOf(astr.charAt(i))!=i)
                    return false;
            }
            return true;
        }
    

    位运算

    属于大神级表演

    • int 32位 long 64位

    • 位运算
      long bitIndex = 1L << c; 表示将二进制的0001(这里是64位,前面的零省略了。)向左边移动c个位置,那么就可以得到唯一对应的站位
      low64 |= bitIndex; 表示和之前的那个拼接起来
      low64 & bitIndex; 与操作,如果没出现过,结果是0,如果出现过,则不会是0

    • ASCII码
      ASCII码是0-127 一共128个,可以代表所有的简单字符。

    思路
    由于ASCII码字符个数为128个,而且题目说了如果你不使用额外的数据结构,会很加分。因此可以使用两个64位的long变量来存储是否出现某个字符,二进制位1表示出现过, 0表示未出现过。具体代码如下

      public boolean isUnique(String astr) {
            long low64 = 0;
            long high64 = 0;
    
            for (char c : astr.toCharArray()) {
                if (c >= 64) {
                    long bitIndex = 1L << (c - 64);
                    if ((high64 & bitIndex) != 0) {
                        return false;
                    }
    
                    high64 |= bitIndex;
                } else {
                    long bitIndex = 1L << c;
                    if ((low64 & bitIndex) != 0) {
                        return false;
                    }
    
                    low64 |= bitIndex;
                }
    
            }
    
            return true;
        }
    
    

    这里还看到如下一段阐述

    如果我是面试官,我会希望看到什么?
    
    可能有点偏题,毕竟这里主要就是做题的地方。。
    
    如果我是面试官,会考虑主要考察什么,就我的工作经验看,大多数主要是招聘工程师的,面试者如果什么问题都没有,直接写个二重循环搞定,会首先给个50分,如果能写点判断字符串是否为null的,60分。
    
    直接上手什么bitset,什么位运算的,我会先问他,题目中有没有交代字符串的字符一定是26个英文字母?如果是unicode环境,你是不是要准备2^16/8个字节的空间?在实际项目中,风险可控,结果可期更重要,绝大多数时候不在乎那点时间和资源。
    
    所以我期望面试者不要急于解答,我希望他先问我问题:
    
    字符串的字符范围,如果我告诉他,26个小写英文字母,那可能一开头直接判断如果字符长度>26, 直接返回False,做到这一点的,80分
    如果我告诉他ascii字符集,然后他的代码里有边界检查,并且针对不同的范围有不同的侧重点,比如说ascii字符集,那也就是128个可能性,16个字节的位运算比较好
    如果我告诉他是unicode,没有字符范围,老老实实排序再判断是比较符合我对工程师的要求的,因为算法性能稳定,没有额外资源要求,一眼看出没什么不可预见的风险,100分。
    就是说,有些东西,没想到或者一时没想到根本不是问题,日常工作中稍微提示一下即可,但是缜密的思维对于程序员来说更重要。
    

    一道看似平平无奇的面试题,解法多种多样。很多时候我们在工作中的时候,在大多数情况下只会写一种解决方案,甚至你也只会想一种解决方法,也不会去比较哪个更优秀。但如果真正的有这种思考的态度,或许做技术久了,差距就出来了

  • 相关阅读:
    训练yolov5识别木块的模型
    八叉树分割点云并优化网格实验记录
    八叉树分割点云实验记录
    给pcd添加头
    C++绘制点云 日志记录
    点云最小包围盒
    java list洗牌
    训练yolov5识别小黄球模型
    八叉树分割点云实验记录2
    pcd中 毫米转为米
  • 原文地址:https://www.cnblogs.com/mxjhaima/p/13914405.html
Copyright © 2020-2023  润新知