华为技术面

文章目录

  • 手撕代码
    • 流程
    • 题目描述
    • 方法介绍
    • 面试官评价
    • 思维扩展
  • 项目描述
  • 技术问题
    • 内存
      • 说明下C++的内存分配情况,栈和队列的区别以及程序员如何分配回收内存?
      • C++程序员和Java程序员有一个很大的区别,就是C++对内存管理由程序员完成,因此会经常出现一个问题,内存泄漏,你了解这个问题吗?
      • 你了解了内存泄漏,你觉得C++程序员应该用什么办法去避免这个问题呢?
      • 既然提到了智能指针,智能指针呢是一个类,一个类就有自己的数据和方法,那你认为智能指针需要什么样的数据呢?
    • map
      • 对于STL库中的map,说说你的理解?
      • map的键值有什么特点,可以为哪些数据类型?
      • 如果map的键值为自定义的数据类型,如何保证键值的唯一性

华为机试的博客让我疯狂涨粉,这找华为OD工作的人也实在太多了哈哈,下面我将详细介绍我的面试经历

手撕代码

流程

面试官给出题目描述,现场敲代码,面试官会通过屏幕共享观察面试者写代码,通过面试者的解释说明,了解到面试者的思考过程。

题目描述

一个仓库当中有50个箱子,仓库中有3个不同的取货物的机器人,机器人A每次可以取1个货物,机器人B每次可以取2个货物,机器人C每次可以取3个货物,三个机器人合作将仓库搬空。如果只是用机器人A取50次货物,将仓库搬空,我们记录为“AAAAA…”(50个), 这便是一个机器人工作序列。那么请问,存在多少种不同的工作序列可以将仓库搬空?
(注:当仓库只剩下一个货物时,必须用A搬运,不可以用B/C;当仓库里剩下两个货物时,不可用C搬运)

方法介绍

这题是很普遍的跳房子,跳台阶问题,力扣有类似的题目:青蛙跳台阶
我使用的方法是动态规划,使用dp[i]表示搬运i个箱子有多少种工作序列,显然1个箱子只有一种A,两个箱子有两种AA和B,三个箱子有4种,分别是AAA,AB,BA和C,当i大于3时,dp[i]=dp[i-1]+dp[i-2]+dp[i-3],这是动态转移方程,我面试过程中写的代码如下:

#include
using namespace std;

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    vector<long long> dp(51);
    dp[0] = 1;
    for (int i = 1; i <= 50; i++) {
        dp[i] += dp[i - 1];
        if (i >= 2) dp[i] += dp[i - 2];
        if (i >= 3) dp[i] += dp[i - 3];
    }
    cout << dp[50];
    return 0;
}

面试官评价

我完成结果后,面试官向我说明了这道题的两个坑,
第一个坑,这题理论上可以用两种方法,一种时递归,一种是动态规划,但对于50的范围进行递归,会出现爆栈的问题,因为我不习惯使用递归实现,刚好躲过了这个坑,各位小伙伴们手撕代码的时候注意爆栈问题哟
第二个坑,这题最后的结果超过的int类型的表示范围,必须使用long long,最后的结果才会正确,我最初也使用的int类型,在调试过程中,发现dp中有一些值是负数,则表明出现溢出,幸运的改正过来。

思维扩展

在手撕代码的最后,面试官关于这题提出一个新的问题,假如要求对1000个箱子求有多少种不同的序列,这个结果超过了long long所能表示的范围,你有什么办法解决这个问题?
在面试官的提示下,我才想到使用string类型来表示最后的结果,由于结果用string表示,所以需要实现由string表示的数字的加法,方法实现为将两个需要相加的string倒置,再通过每位相加以及进位机制完成加法运算,最后相加得到的string倒置即为加法结果。

项目描述

关于这一部分,就是先简单介绍自己的项目经历,面试官会对其感兴趣的进行提问,我的面试官主要针对我项目中的多线程进行了提问,类似于有没有涉及多线程保护以及如何实现的,会由浅入深,具体到如何设计与实现。这主要与面试官的擅长领域和兴趣点挂钩。

技术问题

我面试时的技术问题有内存和map两大类,都是由浅入深

内存

说明下C++的内存分配情况,栈和队列的区别以及程序员如何分配回收内存?

  • 栈:由编译器管理分配和回收,存放局部变量和函数参数。
  • 堆:由程序员管理,需要⼿动 new malloc delete free 进⾏分配和回收,空间较⼤,但可能会出现内存泄漏和空闲碎⽚的情况。
  • 全局/静态存储区:分为初始化和未初始化两个相邻区域,存储初始化和未初始化的全局变量和静态变量。
  • 常量存储区:存储常量,⼀般不允许修改。
  • 代码区:存放程序的⼆进制代码。

C++程序员和Java程序员有一个很大的区别,就是C++对内存管理由程序员完成,因此会经常出现一个问题,内存泄漏,你了解这个问题吗?

内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。(对于内存泄漏这个专业词汇我压根不了解,面试官给我解释了后引出后面的问题)

你了解了内存泄漏,你觉得C++程序员应该用什么办法去避免这个问题呢?

可以通过智能指针解决,智能指针其作⽤是管理⼀个指针,避免程序员申请的空间在函数结束时忘记释放,造成内存泄漏这种情况滴发⽣。然后使⽤智能指针可以很⼤程度上的避免这个问题,因为智能指针就是⼀个类,当超出了类的作⽤域是,类会⾃动调⽤析构函数,析构函数会⾃动释放资源。所以智能指针的作⽤原理就是在函数结束时⾃动释放内存空间,不需要⼿动释放内存空间。(刚好C++八股文中提到过,所有了解一丢丢,然后继续深入了)

既然提到了智能指针,智能指针呢是一个类,一个类就有自己的数据和方法,那你认为智能指针需要什么样的数据呢?

定义智能指针的通用技术是采用一个引用计数(use count)。智能指针类将一个计数器与类指向的对象相关联。引用计数跟踪该类有多少个对象共享同一个指针。引用计数为0时,删除对象。(对于这类底层的问题,即使我不会也不了解,面试官还是让我进行思考,应该需要怎样的数据和方法,如果这类问题在)

map

对于STL库中的map,说说你的理解?

map的键值有什么特点,可以为哪些数据类型?

如果map的键值为自定义的数据类型,如何保证键值的唯一性

你可能感兴趣的:(面试,职场和发展)