【2022-08-31】华为秋招笔试三道编程题

恭喜发现宝藏!搜索公众号【TechGuide】回复公司名,解锁更多新鲜好文和互联网大厂的笔经面经,目前已更新至美团、微软…
作者@TechGuide【全网同名】
点赞再看,养成习惯,您动动手指对原创作者意义非凡🤝

第一题:字符串压缩

题目描述

给定一段英文句子和一个英文单词列表。 英文句子包含英文单词和标点符号,其中:

  1. 英文单词只包含[a-zA-Z]范围内的字符;
  2. 标点符号包括逗号、句号、双引号(双引号两边至少有一个空格)。

如果列表中有单词在句子中存在(大小写不敏感)且该单词未被双引号包含,则使用该单词在列表中的索引值(索引值从0开始)代替句子中的该单词,如果英文单词列表中存在重复的英文单词,则以该单词最后一次出现的索引值进行替换。

输入描述

第一行:一段英文句子
第二行:英文单词列表
提示:
每个英文单词长度在[150]范围内。
输入的英文句子长度在[0,10000]范围内。
输入的英文单词列表长度在[0,100000]范围内。英文句子中不会出现双引号不匹配的情况。

Hello world.
Good Hello LOOP

解释:hello在英文句子中存在,则使用hello的索引值进行替换,得到结果为1w
orld.

输出描述

替换后的英文句子

1world.

代码

CPP版本
#include<bits/stdc++.h>
using namespace std;
map<string,int>aa;
void change(string &s){
 for(int i=0;i<s.length();i++){
  if(s[i]>='a' &&s[i]<='z'){
   s[i]-=32;
  }
 }
}
bool check(char aa){
 if(aa>='A' && aa<='Z')return true;
 if(aa>='a' && aa<='z')return true;
 return false;
}
int main(){
 string s;
 getline(cin,s);
 string s1;
 int tt=1;
 while(cin>>s1){
//  string s2;
  change(s1);
//  cout<<s1<<' '<<tt<<endl;
  aa[s1]=tt;
  tt++;
  //if(tt>=8)break;//调试用的
 }
 string ans;
 int begin1=0;
 for(int i=0;i<s.length();i++){
  if(s[i]=='"'){
   i++;
   while(i<s.length() &&s[i]!='"')i++;
//   ans+='"';
  }
  while(i<s.length() &&check(s[i])){
   i++;
  }
  if(i==s.length())break;
  string tl=s.substr(begin1,i-begin1);
  begin1=i+1;
  string ts=tl;
  change(tl);
//  cout<<"start"<<tl<<' '<<aa[tl]<<endl;
  if(aa[tl]!=0)ans+=to_string(aa[tl]-1);
  else ans+=ts;
  ans+=s[i];
 }
 cout<<ans<<endl;
 return 0;
}
// vx公众号关注TechGuide 实时题库 闪电速递
JS版本
//前后华为给的代码我忘了,直接写核心

//处理句子和字典
var sentence = inputArrays[0].split(" ")
var dictionary = inputArrays[1].split(" ")
//大小写不敏感,把字典全改大写,句子里面有特殊字符,改不了
dictionary = Array.from(dictionary,item=>item.toUpperCase())
//处理引号内的,思路是定义一个开关。当时引号单词忘了咋拼。。
var isInside = false
for(let i in sentence){
    if(sentence[i]=='"'){
        isInside = !isInside    //开关
        continue    //引号不进行字典查询
    }
    var str = sentence[i].replace(/[^a-zA-Z]/,"")
    //含有特殊字符的话toUpperCase()会报错,在这里卡了蛮久,属于是考场上学知识了
    if(dictionary.includes(str.toUpperCase())){
        //之前用for循环倒序查字典的,过80%,剩下的超时,所以优化,先查有没有
        var j = sentence[i] = dictionary.lastIndexOf(str.toUpperCase())
        //最后的索引,当然lastIndexOf()
        str.length==sentence[i].length? sentence[i]=j:sentence[i]=j+sentence[i][sentence[i].length-1]
        //通过对比长度来看有没有句号逗号,有的话取过来
    }
}
console.log(sentence.join(" ")) 
// vx公众号关注TechGuide 实时题库 闪电速递

第二题:士兵的任务2

题目描述

士兵在迷宫中执行任务,迷宫中危机重重,他需要在在最短的时间内到达指定的位害。你可以告诉上兵他最少需要多长时间吗?
输入一个n*m的迷宫中,迷宫中0为路,1为墙,2为起点,3为终点,4为陷阱,6为炸弹。士兵只能向上下左右四个方向移动,如果路径上为墙,不能移动。已知每走一步需要花费1个单位的时间,走到陷阱上需要花费3个单位的时间,走到炸弹上将会激活炸弹将炸弹上下左右的墙炸为路。

注意点:

  1. 炸弹只能炸聚地,不会炸掉陷阱
  2. 炸弹、陷阱只能发挥一次作用
  3. 迷言为最大为25*25
  4. 用例保证十兵一定有方法能到达终点

输入
输出
样例1
复制 输入:44
1021

输入描述

第一行:n和m
第二行开始:n*m的矩阵

4 4
1 1 1 1
1 6 2 1
1 1 0 1
1 3 1 1

输出描述

最少需要的单位时间

3

解释:
士兵在位置2,向左移动到炸弹上,会将炸弹周围的墙炸掉,向下走两步
即可到达终点

思路

代码

CPP版本
#include <iostream>
#include <queue>
using namespace std;
struct node
{
    int x, y, t;
    node() {}
    node(int a, int b, int c) : x(a), y(b), t(c) {}
    bool operator<(const node &a) const
    {
        return t > a.t;
    }
};

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0};
int g[30][30], vis[30][30];
int n, m, ans = 0;
priority_queue<node> q;

int main()
{
    cin >> n >> m;
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
            cin >> g[i][j];
            if (g[i][j] == 2)
            {
                vis[i][j] = 1;
                q.push(node(i, j, 0));
            }
        }
    }
    while (!q.empty())
    {
        node cur = q.top();
        q.pop();
        for (int i = 0; i < 4; ++i)
        {
            int tx = cur.x + dx[i];
            int ty = cur.y + dy[i];
            if (tx < 0 || ty < 0 || tx >= n || ty >= n || vis[tx][ty] || g[tx][ty] == 1)
                continue;
            if (g[tx][ty] == 3)
            {
                ans = cur.t + 1;
                break;
            }
            vis[tx][ty] = 1;
            if (g[tx][ty] == 4)
                q.push(node(tx, ty, cur.t + 3));
            else if (g[tx][ty] == 6)
            {
                q.push(node(tx, ty, cur.t + 1));
                for (int j = 0; j < 4; ++j)
                {
                    int xx = tx + dx[j];
                    int yy = ty + dy[j];
                    if (g[xx][yy] == 1)
                        g[xx][yy] = 0;
                }
            }
            else
                q.push(node(tx, ty, cur.t + 1));
        }
        if (ans)
            break;
    }
    cout << ans;
    return 0;
}
// vx公众号关注TechGuide 实时题库 闪电速递

第三题:高速公路休息站充电规划 (部分AC)

题目描述

张三购买了一辆续航里程数达1000公里的某自动驾驶新能源车。 某一天车辆充满电后,需从甲城出发前往距离D公里远的乙城,全程走高速。

车载导航提示沿途有N个休息站均可提供充电服务,各休息站均可实时提供当前充电排队时间(小时)。
请协助规划时间最优的休息站充电方案,返回最短的旅行用时。

为方便计算,高速上的行驶速度固定为100公里/小时。 规划时可不必考虑保留安全续航里程数,汽车可以将电完全用光,1000公里续航的汽车按100公里/小时,可以开10个小时。每次充电时间固定为1小时,完成后电量充满。各站点充电排队时间不会变化,充电排队过程不耗电。

输入描述

第一行表示甲乙两城的距离D,单位为公里;
第二行表示沿途的休息站数量N;
第三行起,每行2个数据,分别表示休息站距离甲城的距离,以及充电排队所需时间(小时),(各休息站按离从近到远排序)
0<=D<=1000000,D是100的整数倍
0<=N<=10000

1500
4
300 2
600 1
1000 0
1200 0

输出描述

旅程总计花费的最短时间(小时)
若无法到达终点,则返回-1

16

解释:
最佳方案:只在第3个休息站(位置1000)进行充电
1500公里的行程耗时:15小时
充电排队0小时,充电1小时
最快旅程总计花费16小时

其他方案:在第2个休息站(位置600)进行充电,总计花费17小时
其他方案:在第2个休息站(位置600)和第4个休息站(位置1200)进行充电,总计花费19小时

思路

利用动态规划+加回退搜索
把起始点设为0,每次到达一个新的站点,便进行回退搜索,一直搜索到1000公里以内且距离最远的充电站点k,然后从k站点开始遍历,一直遍历到当前站点,找到最短到达当前站点的时间,然后保存到当前站点的时间数组ans中,不断循环遍历,最终遍历到终点。

代码

#define DEBUG 1
#if DEBUG
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;


int main(void) {
	int n, m;
	//参数输入
	cin >> n;
	cin >> m;

	//初始化站点数组,将起点和终点也纳入数组中
	vector<vector<int>> f(m+2, vector<int>(2));

	//起点的距离和等待时间都设为0
	f[0][0] = 0;
	f[0][1] = 0;
	//终点的距离设为n,等待时间设为0
	f[m+1][0] = n;
	f[m+1][1] = 0;

	//开始加入各个站点
	for (int i = 1; i < m+1; i++) {
		cin >> f[i][0];
		cin >> f[i][1];
		cout << f[i][0] << ' ';
		cout << f[i][1] << ' ';

	}

	//初始化到达站点的时间,将起点和终点也纳入数组中
	vector<int> ans(m + 2);
	ans[0] = 0;

	//开始计算各个站点
	for (int i = 1; i < m + 2; i++) {
		//将所有距离在1000以内的站点找出来
		int k = i - 1;
		while (k > 0 && (f[i][0] - f[k][0] < 1000)){
			k--;
		}
		//这里除了起始站点以外,多超了一个站点,因此k需要加一
		if (k != 0) {
			k++;
		}
		//对每个可以直接到达的站点进行遍历,找出最小的时间站点
		int min_time = INT_MAX;
		for (; k < i; k++) {
			int cur_time = (f[i][0] - f[k][0]) / 100 + ans[k] + f[i][1];
			if (k != 0) {
				cur_time++;
			}
			min_time = min(min_time, cur_time);
		}

	}
	getchar();
	cout << ans[m+1] << endl;

	getchar();

}
// vx公众号关注TechGuide 实时题库 闪电速递
  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
1.static有什么用途?(请至少说明两种) 1)在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 2) 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。 3) 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用 2.引用与指针有什么区别? 1) 引用必须被初始化,指针不必。 2) 引用初始化以后不能被改变,指针可以改变所指的对象。 3) 不存在指向空值的引用,但是存在指向空值的指针。 3.描述实时系统的基本特性 在特定时间内完成特定的任务,实时性与可靠性。 4.全局变量和局部变量在内存中是否有区别?如果有,是什么区别? 全局变量储存在静态数据库,局部变量在堆栈。 5.什么是平衡二叉树? 左右子树都是平衡二叉树 且左右子树的深度差值的绝对值不大于1。 6.堆栈溢出一般是由什么原因导致的? 没有回收垃圾资源。 7.什么函数不能声明为虚函数? constructor函数不能声明为虚函数。 8.冒泡排序算法的时间复杂度是什么? 时间复杂度是O(n^2)。 9.写出float x 与“零值”比较的if语句。 if(x>0.000001&&x<-0.000001) 10.Internet采用哪种网络协议?该协议的主要层次结构? Tcp/Ip协议 主要层次结构为: 应用层/传输层/网络层/数据链路层/物理层。 11.Internet物理地址和IP地址转换采用什么协议? ARP (Address Resolution Protocol)(地址解析協議) 12.IP地址的编码分为哪俩部分? IP地址由两部分组成,网络号和主机号。不过是要和“子网掩码”按位与上之后才能区分哪些是网络位哪些是主机位。 13.用户输入M,N值,从1至N开始顺序循环数数,每数到M输出该数值,直至全部输出。写出C程序。 循环链表,用取余操作做 14.不能做switch()的参数类型是: switch的参数不能为实型。 1.写出判断ABCD四个表达式的是否正确, 若正确, 写出经过表达式中 a的值(3分) int a = 4; (A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++); a = ? 答:C错误,左侧不是一个有效变量,不能赋值,可改为(++a) += a; 改后答案依次为9,10,10,11 2.某32位系统下, C++程序,请计算sizeof 的值(5分). char str[] = “http://www.ibegroup.com/” char *p = str ; int n = 10; 请计算 sizeof (str ) = ?(1) sizeof ( p ) = ?(2) sizeof ( n ) = ?(3) void Foo ( char str[100]){ 请计算 sizeof( str ) = ?(4) } void *p = malloc( 100 ); 请计算 sizeof ( p ) = ?(5) 答:(1)17 (2)4 (3) 4 (4)4 (5)4 3. 回答下面的问. (4分) (1).头文件中的 ifndef/define/endif 干什么用?预处理 答:防止头文件被重复引用 (2). #i nclude 和 #i nclude “filename.h” 有什么区别? 答:前者用来包含开发环境提供的库头文件,后者用来包含自己编写的头文件。 (3).在C++ 程序中调用被 C 编译器编译后的函数,为什么要加 extern “C”声明? 答:函数和变量被C++编译后在符号库中的名字与C语言的不同,被extern "C"修饰的变 量和函数是按照C语言方式编译和连接的。由于编译后的名字不同,C++程序不能直接调 用C 函数。C++提供了一个C 连接交换指定符号extern“C”来解决这个问。 (4). switch()中不允许的数据类型是? 答:实型 4. 回答下面的问(6分) (1).Void GetMemory(char **p, int num){ *p = (char *)malloc(num); } void Test(void){ char *str = NULL; GetMemory(&str, 100); strcpy(str, "hello"); printf(str); } 请问运行Test 函数会有什么样的结果? 答:输出“hello” (2). void Test(void){ char *str = (char *) malloc(100); strcpy(str, “hello”); free(str); if(str != NULL){ strcpy(str, “world”); printf(str); } } 请问运行Test 函数会有什么样的结果? 答:输出“world” (3). char *GetMemory(void){ char p[] = "hello world"; return p; } void Test(void){ char *str = NULL; str = GetMemory(); printf(str); } 请问运行Test 函数会有什么样的结果? 答:无效的指针,输出不确定 5. 编写strcat函数(6分) 已知strcat函数的原型是char *strcat (char *strDest, const char *strSrc); 其中strDest 是目的字符串,strSrc 是源字符串。 (1)不调用C++/C 的字符串库函数,请编写函数 strcat 答: VC源码: char * __cdecl strcat (char * dst, const char * src) { char * cp = dst; while( *cp ) cp++; /* find end of dst */ while( *cp++ = *src++ ) ; /* Copy src to end of dst */ return( dst ); /* return dst */ } (2)strcat能把strSrc 的内容连接到strDest,为什么还要char * 类型的返回值? 答:方便赋值给其他变量 6.MFC中CString是类型安全类么? 答:不是,其它数据类型转换到CString可以使用CString的成员函数Format来转换 7.C++中为什么用模板类。 答:(1)可用来创建动态增长和减小的数据结构 (2)它是类型无关的,因此具有很高的可复用性。 (3)它在编译时而不是运行时检查数据类型,保证了类型安全 (4)它是平台无关的,可移植性 (5)可用于基本数据类型 8.CSingleLock是干什么的。 答:同步多个线程对一个数据类的同时访问 9.NEWTEXTMETRIC 是什么。 答:物理字体结构,用来设置字体的高宽大小 10.程序什么时候应该使用线程,什么时候单线程效率高。 答:1.耗时的操作使用线程,提高应用程序响应 2.并行操作时使用线程,如C/S架构的服务器端并发线程响应用户的请求。 3.多CPU系统中,使用线程提高CPU利用率 4.改善程序结构。一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独 立的运行部分,这样的程序会利于理解和修改。 其他情况都使用单线程。 11.Windows是内核级线程么。 答:见下一 12.Linux有内核级线程么。 答:线程通常被定义为一个进程中代码的不同执行路线。从实现方式上划分,线程有两 种类型:“用户级线程”和“内核级线程”。 用户线程指不需要内核支持而在用户程序 中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度 和管理线程的函数来控制用户线程。这种线程甚至在象 DOS 这样的操作系统中也可实现 ,但线程的调度需要用户程序完成,这有些类似 Windows 3.x 的协作式多任务。另外一 种则需要内核的参与,由内核完成线程的调度。其依赖于操作系统核心,由内核的内部 需求进行创建和撤销,这两种模型各有其好处和缺点。用户线程不需要额外的内核开支 ,并且用户态线程的实现方式可以被定制或修改以适应特殊应用的要求,但是当一个线 程因 I/O 而处于等待状态时,整个进程就会被调度程序切换为等待状态,其他线程得不 到运行的机会;而内核线程则没有各个限制,有利于发挥多处理器的并发优势,但却占 用了更多的系统开支。 Windows NT和OS/2支持内核线程。Linux 支持内核级的多线程 13.C++中什么数据分配在栈或堆中,New分配数据是在近堆还是远堆中? 答:栈: 存放局部变量,函数调用参数,函数返回值,函数返回地址。由系统管理 堆: 程序运行时动态申请,new 和 malloc申请的内存就在堆上 14.使用线程是如何防止出现大的波峰。 答:意思是如何防止同时产生大量的线程,方法是使用线程池,线程池具有可以同时提 高调度效率和限制资源使用的好处,线程池中的线程达到最大数时,其他线程就会排队 等候。 15函数模板与类模板有什么区别? 答:函数模板的实例化是由编译程序在处理函数调用时自动完成的,而类模板的实例化 必须由程序员在程序中显式地指定。 16一般数据库若出现日志满了,会出现什么情况,是否还能使用? 答:只能执行查询等读操作,不能执行更改,备份等写操作,原因是任何写操作都要记 录日志。也就是说基本上处于不能使用的状态。 17 SQL Server是否支持行级锁,有什么好处? 答:支持,设立封锁机制主要是为了对并发操作进行控制,对干扰进行封锁,保证数据 的一致性和准确性,行级封锁确保在用户取得被更新的行到该行进行更新这段时间内不 被其它用户所修改。因而行级锁即可保证数据的一致性又能提高数据操作的迸发性。 18如果数据库满了会出现什么情况,是否还能使用? 答:见16 19 关于内存对齐的问以及sizof()的输出 答:编译器自动对齐的原因:为了提高程序的性能,数据结构(尤其是栈)应该尽可能 地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问 ;然而,对齐的内存访问仅需要一次访问。 20 int i=10, j=10, k=3; k*=i+j; k最后的值是? 答:60,此考察优先级,实际写成: k*=(i+j);,赋值运算符优先级最低 21.对数据库的一张表进行操作,同时要对另一张表进行操作,如何实现? 答:将操作多个表的操作放入到事务中进行处理 22.TCP/IP 建立连接的过程?(3-way shake) 答:在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。   第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状 态,等待服务器确认; 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个 SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;   第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1) ,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 23.ICMP是什么协议,处于哪一层? 答:Internet控制报文协议,处于网络层(IP层) 24.触发器怎么工作的? 答:触发器主要是通过事件进行触发而被执行的,当对某一表进行诸如UPDATE、 INSERT 、 DELETE 这些操作时,数据库就会自动执行触发器所定义的SQL 语句,从而确保对数 据的处理必须符合由这些SQL 语句所定义的规则。 25.winsock建立连接的主要实现步骤? 答:服务器端:socker()建立套接字,绑定(bind)并监听(listen),用accept() 等待客户端连接。 客户端:socker()建立套接字,连接(connect)服务器,连接上后使用send()和recv( ),在套接字上写读数据,直至数据交换完毕,closesocket()关闭套接字。 服务器端:accept()发现有客户端连接,建立一个新的套接字,自身重新开始等待连 接。该新产生的套接字使用send()和recv()写读数据,直至数据交换完毕,closesock et()关闭套接字。 26.动态连接库的两种方式? 答:调用一个DLL中的函数有两种方法: 1.载入时动态链接(load-time dynamic linking),模块非常明确调用某个导出函数 ,使得他们就像本地函数一样。这需要链接时链接那些函数所在DLL的导入库,导入库向 系统提供了载入DLL时所需的信息及DLL函数定位。 2.运行时动态链接(run-time dynamic linking),运行时可以通过LoadLibrary或Loa dLibraryEx函数载入DLL。DLL载入后,模块可以通过调用GetProcAddress获取DLL函数的 出口地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免导入库文件了 。 27.IP组播有那些好处? 答:Internet上产生的许多新的应用,特别是高带宽的多媒体应用,带来了带宽的急剧 消耗和网络拥挤问。组播是一种允许一个或多个发送者(组播源)发送单一的数据包 到多个接收者(一次的,同时的)的网络技术。组播可以大大的节省网络带宽,因为无 论有多少个目标地址,在整个网络的任何一条链路上只传送单一的数据包。所以说组播 技术的核心就是针对如何节约网络资源的前提下保证服务质量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值