小米自动驾驶 C++ 面经

作者 | BrianLee 编辑 | 自动驾驶之心

原文链接:https://zhuanlan.zhihu.com/p/546531693

点击下方卡片,关注“自动驾驶之心”公众号

戳我-> 领取自动驾驶近15个方向学习路线

>>点击进入→自动驾驶之心BEV感知技术交流群

本文只做学术分享,如有侵权,联系删文

一面

基础

  • 虚拟内存相关详细讲一下

  • 讲讲左值和右值

  • 什么时候使用右值

  • 完美转发

  • 假如 a 是 T 的左值引用,T 是 int&& 类型的,那么 a 实际上是什么

  • 讲一下智能指针

  • shared_ptr 和 unique_ptr 区别,以及性能对比

  • weak_ptr 及其作用

  • shared_ptr 是线程安全的吗

  • lambda 表达式有哪些捕获类型

  • 讲讲多态及实现机制

  • 虚基类

  • 多继承的时候,虚函数表指针怎么存using std::cin 和 在

  • using namespace std 后使用cin有什么区别

  • 元编程

项目

  • 详细介绍

  • MSRA实习项目

  • 对交易预测输入和输出需要存储,这个空间消耗大概多大

思考题

一个有环链表,两个速度不一样的指针移动,起始位置也不一定一样,它们一定相遇吗

Coding

数据中最小的k个数

class Solution {
private:
    int randInRange(int l, int r) {
        srand(time(0));
        return rand() % (r - l + 1) + l;
    }
    int partition(vector<int> &input, int l, int r) {
        if (l >= r)    return l;
        int idx = randInRange(l, r);
        swap(input[idx], input[r]);
        int large = l - 1;
        for (int i = l; i < r; ++ i) {
            if (input[i] < input[r]) 
                swap(input[++ large], input[i]);
        }
        swap(input[++ large], input[r]);
        return large;
    }
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int n = input.size();
        int l = 0, r = n - 1;
        vector<int> res;
        while (l <= r) {
            int idx = partition(input, l, r);
            if (idx + 1 == k) {
                res.assign(input.begin(), input.begin() + k);
                return res;
            } else if (idx + 1 < k)
                l = idx + 1;
            else 
                r = idx - 1;
        }
        return res;
    }
};

二面

基础

  • 首先介绍了自动驾驶系统涉及的研发方向,问我对哪个感兴趣

  • 自我介绍

  • 发现性能瓶颈使用过什么方法

  • 如何发现死锁

  • 在开发时制定什么样的规则可以避免死锁

  • 如何调试内存泄露

  • 如何调试 core dump

  • 虚拟内存介绍

  • 每个进程的虚拟内存有多大

  • 如果物理内存大于 4G,可以不使用虚拟内存吗(安全性)

  • 线程切换要进入内核态吗

  • 一个很大的二维数组存在内存中,是按行读取快还是按列读取快(CPU cache,局部性原理)

  • map 和 unordered_map区别

  • unordered_map 使用什么方法解决 hash 冲突

Coding

LRU,要求自己实现双向链表

#include <bits/stdc++.h>
using namespace std;

struct Node {
    int key;
    int value;
    Node *left;
    Node *right;
    Node(int k, int v): key(k), value(v) {
        left = nullptr;
        right = nullptr;
    }
    Node(int k, int v, Node *l, Node *r): key(k), value(v), left(l), right(r) {} 
};

struct BiList {
    Node *head;
    Node *tail;
    BiList() { 
        head = new Node(0, 0); 
        tail = head;
    }
    void insert_front(Node *node) {
        auto first = head->right;
        node->right = first;
        head->right = node;
        node->left = head;
        if (first) {
            first->left = node;
        }
        if (tail == head)
            tail = head->right;
    }
    pair<int, int> erase_end() {
        if (tail == head)
            return {-1, -1};
        Node *tmp = tail;
        tmp->left->right = nullptr;
        tail = tmp->left;
        int key = tmp->key, val = tmp->value;
        delete tmp;
        return {key, val};
    }
    void erase(Node *node) {
        if (node == tail)
            tail = node->left;
        auto left = node->left;
        auto right = node->right;
        left->right = right;
        if (right)
            right->left = left;
        delete node;
    }
    Node *first() {
        return head->right;
    }
    ~BiList() {
        Node *ptr = head;
        while (ptr) {
            Node *tmp = ptr->right;
            delete ptr;
            ptr = tmp;
        }
    }
};

class LRUcache {
private:
    int cap;
    BiList *lst;
    unordered_map<int, Node*> mp;
public:
    LRUcache(int k): cap(k) {
        lst = new BiList();
    }
    void set(int key, int value) {
        if (mp.find(key) == mp.end()) {
            if (mp.size() == cap) {    //evict
                auto p = lst->erase_end();
                int rm_key = p.first;
                mp.erase(rm_key);
            }
        } else {
            auto node = mp[key];
            lst->erase(node);
        }
        lst->insert_front(new Node(key, value));
        mp[key] = lst->first();
    }
    
    int get(int key) {
        if (mp.find(key) == mp.end())
            return -1;
        auto node = mp[key];
        int value = node->value;
        lst->erase(node);
        lst->insert_front(new Node(key, value));
        mp[key] = lst->first();
        return value;
    }
    ~LRUcache() {
        delete lst;
    }
};

int main() {
    int n, k;
    cin >> n >> k;
    LRUcache cache(k);
    vector<int> res;
    for (int i = 0; i < n; ++ i) {
        int opt;
        cin >> opt;
        if (opt == 1) {
            int x, y;
            cin >> x >> y;
            cache.set(x, y);
        } else {
            int x;
            cin >> x;
            res.push_back(cache.get(x));
        }
    }
    for (int num : res) 
        cout << num << " ";
    return 0;
}

总结

LRU 出现频率真的好高。。

拼团钜惠立减100!

208f4d9eedbb97c4295e5ff0e2e4ac61.png

学习C++的难点和解决方案

尽管C++在自动驾驶行业中应用广泛,但许多学习者在学习C++时往往面临各种挑战。从语法规则到高级应用,如何快速掌握C++的关键知识点和思维方式,是每个C++初学者都会遇到的难题。如果还需要同时学习自动驾驶相关模块算法的知识,就更让初学者感到畏惧和艰难。

虽然很多人在学校里有机会学习C++,但学校的课程质量令人不敢恭维:

  • 学校的C++编程课程过于注重语法知识的学习,而较少关注实际编码,导致学生对概念一知半解,一动手就迷糊;

  • C++涉及面广,而学校的教学时间有限,所以学习往往碎片化,重要知识点无法系统地学习;

  • 学校老师大多没有实际项目开发经验,很难将C++应用场景和实际工作需求结合,和自动驾驶结合就更加稀少;

  • 许多学校还在使用着陈旧的教材与开发工具,往往落后实际应用一二十年,大量C++新特性没有涉及。

此外,网络上的C++课程汗牛充栋,良莠不齐。而且这些课程都更专注于C++本身的语法和特性,一般是面向通用领域,没有结合特定领域而展开,或者以互联网后端服务为主。相比之下,自动驾驶行业对C++有非常独特的需求,比如自动驾驶核心算法不需要考虑多机冗余和高并发, 而是涉及大量的数学运算、矩阵操作、图像处理等,需要利用C++进行高效的底层实现;自动驾驶还需要考虑系统架构、并发、硬件访问等问题,这需要工程化的C++编程思维。因此,虽然已经有大量C++课程,但依然缺乏面向自动驾驶领域、具备实战案例的C++课程。

自动驾驶之心通过与行业内多名资深C++工程师交流,结合学习的难点和痛点,推出了首个面向自动驾驶与具身智能量产级的C++编程课程。本课程将帮助学习者克服这些难题,通过丰富的自动驾驶实例和项目实践,让C++变得更为亲近和易学。本课程会秉承“以终为始”的概念,所有案例均来源于自动驾驶行业,以丰富的自动驾驶项目案例,生动地讲解C++的概念和语法,使学员快速把握C++精髓。还将分享资深算法大咖的实战经验和工作感悟,帮助学员更加游刃有余地应对工作中的问题和规划自己的未来。

在一期大获成功的同时,我们也在思考,哪些需要改进,只有根据反馈自我革新,才能永葆生命力和竞争力。团队和朝峰老师进行了深入探讨,结合一期学员的疑问和反馈,决定对大纲进行全面优化,增加一些实际开发中需要用到的细节东西(常用工具库的细节、资源管理更深入细节、实战项目的增加等等),将很多高级部分进行了升级和细化,让刚入门自动驾驶和机器人领的小伙伴能循序渐进的学习,让有基础的同学更好的进阶,工作中游刃有余。

二期新大纲

5505a91aa55b28027afdd8d9ce874875.png

下面是vip群内的日常答疑,干货满满!

69283fceb8b33ec012844eb7c6eea0e1.png 拼团钜惠立减100!

07586e25e0bba0de955a3335b6a023e3.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值