云泥科技_04123

24 年 12 月 3 日 星期二 (已编辑)
1682 字
9 分钟

一面

算法

上来就是算法题

力扣原题 删除字符使频率相同
简单题 不过通过率只有24% 什么罐头我说

暴力方法很好写 不过当时直接开始写优化的方法 所以花了很长时间

复盘

cpp
// 暴力方法
class Solution {

public:
    bool isEqual(unordered_map<char, int> c_frac){
        int f = c_frac.begin()->second;
        for (auto p:c_frac){
            if (p.second != f){
                return false;
            }
        }
        return true;
    }


    bool equalFrequency(string word) {
        // 遍历每个可能的删除字符
        for (int i = 0; i < word.size(); i ++){
            unordered_map<char, int> c_frac;
            for (int j = 0; j < word.size(); j ++){
                if (i != j){
                    c_frac[word[j]] ++;
                }
            }
            // 检查删除字符后每个字符出现的频率是否相同
            if (isEqual(c_frac)){
                return true;
            }
        }
        return false;
    }
};

优化方法
实际上如果频率的个数大于2 那么一定不满足条件
如果频率的个数等于2 那么需要检查两个频率是否相等
如果频率的个数等于1 那么一定满足条件

cpp
class Solution {
public:
    bool equalFrequency(string word) {
        unordered_map<char, int> c_frac;
        for (auto c:word){
            c_frac[c] ++;
        }

        vector<int> frac;
        for (auto p:c_frac){
            frac.push_back(p.second);
        }
        sort(frac.begin(), frac.end());
        // 只有一个
        // 如果除了最后一个全相等 最后一个比其他多了1个 删除最后一个多的
        // 如果最小的只有一个 并且其他全相等 删除第一个
        return frac.size() == 1
         ||
         frac[0] == 1 && equal(frac.begin() + 2, frac.end(), frac.begin() + 1)
         ||
         frac[frac.size() - 1] == frac[frac.size() - 2] + 1 && equal(frac.begin() + 1, frac.end() - 1, frac.begin());
    }
};

python基础

面试官问我简历上写的python和java,写算法有用cpp,希望我被问哪方面的(

python基本的集合类

list dict set tuple(没打上来 因为的确不怎么注意这个) 答字符串被认为是列表的一种
面试官强调说tuple是非常pythonic的一个集合类

tuple和list的区别

tuple的元素不可变

list和dict区别

先说了一下list和dict的共同点 list实际上也是一个hash,一个索引映射到一个元素
不同点就是 list的元素存储的都是指针 大小都是相同的 而dict是变长的 每个元素大概率是不相同的

答这么多 实际上没有在点子上
面试官说自己问的太宏大了( 他只是希望我回答 dict是无序的 list有序的
难绷的 是我自己没有搞清楚二者最关键的区别

复盘
dict使用哈希函数将 key 映射到存储位置 不保证顺序 因此是无序的
list是一个顺序存储的数组结构,内部使用连续的空间存储元素指针

面相对象

继承是什么 java和python的继承有什么不同

假设代码中的一些类有一些相同的方法和属性 如果不使用继承 那么这些方法和属性只能放在各个类中 导致代码非常冗余
有个办法就是将共同的方法和属性抽象泛化到一个父类中,子类继承父类来减少代码冗余

java和python的继承除了语法不同(java是通过extends关键字 python是括号)之外
java只有单继承 python支持多继承(class C(A, B):)

MRO (Method Resolution Order) python多继承的解析顺序

没答上来

python支持多继承 就需要处理一些父类方法冲突的问题 比如两个继承的父类中有名字相同的方法或者属性
c3算法

  • 子类优先原则:子类在父类前面
  • 从左到右原则:多个父类时保持声明顺序
  • 单调性原则:如果 C 的 MRO 中 A 在 B 前面,那么所有继承 C 的类的 MRO 中,A 也必须在 B 前面

工程

fastapi 处理报错的全局中间件

之前并没有详细了解中间件的概念 但是知道有个东西做这样的事情
回答的是有一个exception_handler的装饰器 可以捕获异常

在FastAPI中,定义中间件通常是通过装饰器或在应用实例上添加中间件函数来实现的。中间件的设计使得它们可以灵活地插入到请求-响应的生命周期中,从而实现复杂的请求处理逻辑。

复盘

fastapi的中间件函数有requestresponse两个参数
主要有before_requestafter_request两种
其次还有http方法 可以对特定的http方法进行处理

spring boot 类似的中间件

回答了类似的报错处理中间件和访问拦截器 还说了AOP

复盘

spring boot 的中间件和fastapi的中间件是类似的 都是插入到请求-响应的生命周期中

spring中主要有filter、interceptor、AOP和exceptionHandler四种
其中filter是servlet中的概念 拦截请求和响应
interceptor是spring中的概念 拦截请求
AOP是spring中的概念 面向切面编程
exceptionHandler是spring中的概念 处理报错

数据库

数据库优化查询

建立索引 比如people表中的age字段
对age建立索引 mysql会建立一个新的树 将age作为key 将对应的主键放在叶子结点作为value
在根据age进行查询的时候 直接通过树进行查找 这样就大大提高了查询效率

redis常用数据结构

string、list、hash、set、zset(sorted set)

说了java项目使用redis存邮箱的验证码 限流等

python装饰器和java注解

python的装饰器是什么

装饰器是用来增强函数或方法的功能
可以在执行函数前或后执行一些操作
和java的aop类似

fastapi的项目使用装饰器来完成redis存缓存

java的注解是什么

注解是用来给类、方法、属性等添加一些额外的信息
分为编译时注解和运行时注解
运行时注解使用反射机制,反射允许程序在运行时获取类的信息并操作类的属性和方法。比如@Autowired注解,Spring容器会在运行时通过反射找到被注解的属性,并注入对应的实例。一般运行时注解比较常用。

编译时注解使用apt(Annotation Processing Tool)工具,在编译阶段处理注解并生成新的代码。比如Lombok的@Data注解会在编译时生成getter/setter方法。相比运行时注解,编译时注解不会带来运行时的性能开销,但功能相对有限。

反射是Java提供的一种机制,允许程序在运行时动态地获取类的信息(包括类的属性、方法、构造器等),并且可以操作这些信息。

文章标题:云泥科技_04123

文章作者:Blank

文章链接:https://blankxiao.github.io/posts/%E9%9D%A2%E7%BB%8F/%E4%BA%91%E6%B3%A5%E7%A7%91%E6%8A%80_04123[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。