记应聘:华为 可信理论、技术与工程实验室 产品数据工程师

简历面

其实对自己的简历还是有点自信的。加上是内推的,这一关过了。

第一轮在线考试

记在前面:
邮件给的硬件模拟题是一些数据结构的基础知识。
软件模拟题是两到代码题,第一道超简单,简单的加法,可能考察一个输入输出。
第二道题是 0交换排序
长度为n的数组乱序存放着0至n-1. 现在只能进行0与其他数的交换,完成以下函数。
这是我第一次的代码:

#include
using namespace std;
/**
 * 交换数组里n和0的位置
 * array: 存储[0-n)的数组
 * len: 数组长度
 * n: 数组里要和0交换的数
 */
 //我把这个函数给自己实现了一下,其实他给的意思是让我们直接调用的。
 //前面加了extern,应该是让我们直接调用的.
 //因为extern本身就是说这个函数前面定义好了,这里使用的时候再声明一下。
 //当然也可以是第一次声明的时候,直接这么写。
 //不过,我给实现了之后,下面就报错,说是重定义了这个函数。
extern void swap_with_zero(int* array, int len, int n) {
    if (array[n] == n) {}
    else {
        int j = 0;
        for (int i = 0; i < len; i++) {
            if (array[i] == 0) { j = i; break; }
        }
        //这里是先找到0在哪里。
        int k = 0;
        for (int i = 0; i < len; i++) {
            if (array[i] == n) { k = i; break; }
        }
        //找到n的位置。
        if (n != j) {
            array[j] = array[n];
            array[n] = 0;
        }
        //如果以n为下标的这个数不是0,让0先和这个数交换。
        array[k] = 0;
        array[n] = n;
    }
}
class Solution {
public:
    /**
     * 调用方法swap_with_zero来对array进行排序
     */
    void sort(int* array, int len) {
        for (int i = 0; i < len; i++) {
            swap_with_zero(array, len, i);
        }
    }
};

int main() {
    Solution a;
    int b[10] = { 9,8,7,6,5,4,3,2,1,0 };
    a.sort(b,10);
    for (int i = 0; i < 10; i++) {
        cout << b[i]<<" ";
    }
}

之后,修改了一下。

/**
 * 交换数组里n和0的位置
 * array: 存储[0-n)的数组
 * len: 数组长度
 * n: 数组里要和0交换的数
 */
extern void swap_with_zero(int* array, int len, int n);
class Solution {
public:
    /**
     * 调用方法swap_with_zero来对array进行排序
     */
    void sort(int* array, int len) {
        int j = len - 1;
        while (j >= 0) {
            while (array[j] == j) { j--; }
            if (j >= 0) {
                swap_with_zero(array, len, array[j]);
                swap_with_zero(array, len, j);
            }
            j--;
        }
        //for (int j = len - 1; j > 0; j--) {
        //swap_with_zero(array, len, array[j]);
        //swap_with_zero(array, len, j);
        //}//或者可以换成这三行。
        //之所以要从后面开始,是因为,0最终是排在前面的,从前面开始遇到了0不好处理。
    }
};

接下来,等着第一轮考试了。考完了再记。
考试死的好惨,但还是需要记一下题目。
第一题是,输入一个数字串(长度小于1000),数字之间用逗号隔开,要求,找出所有的素数,去重之后,按照升序输出。
代码如下:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#pragma warning(disable:4996)

int main()
{
	string a;
	cin >> a;
	int j=a.length();  //j记录字符串的长度。
	priority_queue<int>b;   //b记录每一个数。
	int i2 = 0;
	char c='0';
	for (int i = 0; i < j; i++) {
		if (a[i] == '-') { c = '-'; continue; }
		if (a[i] == ',' && c == '-') { i2 = 0; c = '0'; continue; }
		if (a[i] == ',') { b.push(i2); i2 = 0; c = '0'; }
		else {
			i2 = i2 * 10 + ((int)a[i]-48);
		}
	}
	//判断素数
	//2是素数。
	//质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
	//自然数是指用以计量事物的件数或表示事物次序的数。即用数码0,1,2,3,4……所表示的数。
	//自然数由0开始,一个接一个,组成一个无穷的集体。自然数有有序性,无限性。分为偶数和奇数,合数和质数等。
	stack<int>a2;  //存储输出的素数。
	while (!b.empty()) {
		int j3 = b.top();
		bool a3 = true;
		for (int j4 = 2; j4 < sqrt(j3); j4++) {
			if (j3 % j4 == 0) { a3 = false; break; }
		}
		if (a3) {
			a2.push(j3);
		}
		b.pop();
	}
	if (a2.empty()) {
		cout << "empty";
	}
	else {
		int k3 = 0;
		while (a2.top() == 1) {
			a2.pop();
		}
		k3 = a2.top();
		cout << k3;
		a2.pop();
		while (!a2.empty()) {
			if (k3 == a2.top()) {
				a2.pop();
			}
			else {
				cout << ',' << a2.top();
				a2.pop();
			}
		}
	}
	return 0;
}

昨天代码只跑通了66.7%的测试用例,可能是因为没有考虑到负数。

第二题是,个人觉得是一个智能优化的题目,给出8个(小文件数目/需要主机数)的信息,现在给你x个主机,问在最优调度下,最多可以处理多少个小文件。
8个信息是:
记应聘:华为 可信理论、技术与工程实验室 产品数据工程师_第1张图片
今天查了查资料,就是01背包问题,确实属于动态规划,是个优化问题。
思想参见:0 1背包问题
代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#pragma warning(disable:4996)
//这是一个优化问题,或许智能优化里面的01算法?是的。
int main()
{
	//这种题目,他涉及到下标是需要参与使用的,可直接这样定义。
	int w[9] = {0,5,5,4,3,3,3,2,1};
	int v1[9] = {0,620,400,380,500,370,450,300,150};
	int x = 0;
	cin >> x;  //容量是x
	int x2 = x / 10;   //上面的重量数据是除以10之后的。
	if (x2 < 0) { return -1; }
	int* dp = new int[x2+1];  //①如果这里数组大小不是定义成x2+1个。
	
	for (int i = 0; i < x2+1; i++) {   
		dp[i] = 0;
	}
	for (int i = 1; i < 9; i++) {
		for (int v = x2; v >= w[i]; v--) {
			dp[v] = max(dp[v],dp[v-w[i]]+v1[i]);  //②这里dp[v]这个东西就有可能越界。
		}
	}
	int max = -1;
	for (int i = 1; i < x2+1; i++) {
		if (dp[i] > max) {
			max = dp[i];
		}
	}
	cout << max;
	delete[]dp;
	return 0;
}

第三题是,我觉得不难,代码逻辑很简单,就是对数组的操作,但是不知道为啥,通过率0%.就是说,第一行输入N,表示一个数组的元素个数,最多1000000个。第二行输入数组的元素,元素都在-10000到10000之间(大概),第三行输入一个数M,表示下面进行M个操作。接下来就是输入相应的操作。第一个字母是U,表示更新操作,更新第二个输入的数a(下标)到第三个输入的数b(下标)之间的数组元素,每个都更新成,该元素的第三个数k次方。若第一个字母是C,则表示求和,求的是第二个数a(下标)到第三个数b(下标)之间的数组元素之和。
看例子:
输入
5
1 2 3 4 5
3
U 3 4 2 表示更新a[3]到a[4]之间的数,每个数更新成自己的2次方。
C 3 4 输出a[3]到a[4]之间的数的和。只有加法有输出。
C 2 3 类似。
还有一个条件是为了避免次方之后太大,对每一个结果取模 模1234567891.

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#pragma warning(disable:4996)

int main()
{
	int N = 0;
	cin >> N;
	vector<int>a1;
	int m = 0;
	for (int i = 0; i < N; i++) {
		cin >> m;
		a1.push_back(m);
	}
	int M = 0;
	cin >> M;
	for (int i = 0; i < M; i++) {
		char a2;
		cin >> a2;
		if (a2 == 'U') {
			int a = 0; int b = 0; int k = 0;
			cin >> a; cin >> b; cin >> k;
			for (int de = a; de < b + 1; de++) {
				if (k == 0) {a1[de] = 1;}
				else if (k == 1) { break; }
				else {
					for (int i3 = 0; i3 < k - 1; i3++) {
						a1[de] = ((a1[de] % 1234567891) * (a1[de] % 1234567891)) % 1234567891;
					}
				}
			}
		}
		if (a2 == 'C') {
			int a = 0; int b = 0;
			cin >> a; cin >> b;
			int cd = 0;
			for (int de = a; de < b + 1; de++) {
				cd = cd + a1[de];
			}
			cout << cd << endl;
		}
	}
	return 0;
}

另记:关于C++里面将字符串转换成整数的库函数。
以下三个函数属于c标准库, 添加头文件
1.atoi():(把一字符串转换为整数)会扫描参数 nptr字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过isspace( )函数来检测),直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时(’\0’)才结束转换,并将结果返回。如果 nptr不能转换成 int 或者 nptr为空字符串,那么将返回 0。
2.atol():(把一字符串转换为长整形)会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时(’/0’)才结束转换,并将结果返回。
3.atof():(把一个字符串转换为双精度浮点数)会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时 (’/0’)才结束转换,并将结果返回。参数nptr字符串可包含正负号、小数点或E(e)来表示指数部分,如123.456或123e-2。
4.strtod():(将字符串转换为双精度浮点型值,并报告不能被转换的所有剩余数字)strtod()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,到出现非数字或字符串结束时 (’/0’)才结束转换,并将结果返回。若endptr不为NULL,则会将遇到不合条件而终止的nptr中的字符指针由endptr传回。参数nptr 字符串可包含正负号、小数点或E(e)来表示指数部分。如123.456或123e-2。

第1.1轮在线机考

上次那个那么差,应该是没过。但是可能由于走内推,直接给部门员工发过邮件,26号晚还有一个在线机试,这个应该是部门内部的招聘吧。总之,加油。
今天又是凉凉的一晚,只对了0.83道题。
下面是题目:
1.在一个int型整数的bit流中,找到101比特块首次出现的次数以及首次出现的位置,用空格隔开。位置是从右边开始下标为0。如果没找到输出次数为0,下标为-1.并且比特位允许重复使用,即‘10101’中间的那个1可以和前面的和后面的同时组合。这道题过了83.3%。剩下的用例可能是因为负数没考虑?现在证实了,不是负数,但不知道是啥。

#include 
#include 
#include 
using namespace std;

int main() {
	int a;
	cin >> a;
	if (a == 0) {
		cout << 0 << " " << -1;
		return 0;
	}
    //把这个整数转换成二进制
	//这里暂时仅考虑正数
	vector<int>b;  //用于记录转换后的值
	queue<int>b2;
	while (a != 1) {
		int c = 0;
		c = a % 2;
		a = a / 2;
		b2.push(c);
	}
	b2.push(a);
	while (!b2.empty()) {
		b.push_back(b2.front());
		b2.pop();
	}
	int num = 0;  //次数
	int po = 0;  //位置
	bool flag1 = false;  //是否首次
	int first = 0; int second = 0;
	int j = b.size();   //二进制的长度
	while (second < j - 2) {
		while (b[second] != 1) { second++; }
		first = second;
		if ((b[second + 1] == 0) && (b[second + 2] == 1)) {
			second = second + 2; first = second;
			num++;
			if (!flag1)
			{
				po = first - 2; flag1 = true;
			}
		}
		else if (b[second + 1] == 1) { second = second + 1; first = second; }
		else if ((b[second + 1] == 0) && (b[second + 2] == 0)) {
			if (second + 3 < j)
			{
				second = second + 3; first = second;
			}
	    }
	}
	if (num == 0) { cout << 0 << " " - 1; }
	else { cout << num << " " << po; }
	return 0;
}

2.将表格数据转换成文本数据。
表格中的每一行,由若干个字段组成,每个字段可以是整数或是字符串(字符串只包合数字、字母以及特殊字符(这里列举了几个特殊字符,并规定出现的就是这几个)。现在需要将表格中的每一行转换成文本中的每一行。
具体格式如下:
采用逗号分隔不同的字段,数字直接采用10进制的文本存储,字符串的存储规则如下:如果字符串本身出现了逗号以及双引号,则用"a,""“表示a,”。反之,给不给字符串加双引号就无所谓。如abc或者"abc"都可以。
输出格式:第一行输出字符串格式是否正确,正确输出分段的个数,不正确输出error
若正确,则输出每个字段的值,每个字段独占一行。
例如:a,1,“b,”""
输出为:
4
a
− − -- \qquad 备注一下,空的段用这个代替
1
b,"
我一开始的思路是考虑边界情况,一个一个if,尝试了之后,我就放弃了,有点负责。后来我又尝试了字符串的分隔,也有点复杂,经过大佬点拨,现在准备换成利用栈的思想来解。
(当时在做这道题的时候,还被一个错误思想卡住了,一直觉得那个整数需要算出具体的数值,但是后来想想,完全不需要嘛,只需要保留原来的整数,还是以字符串的形式,直接输出就可以了)
但最后实现的时候,又换成了队列。。

#include 
#include 
#include 
#include 
using namespace std;

int main() {
	string s;
	cin >> s;
	queue<char>s2;  //中间临时暂存字符串
	vector<char>s21;   //""这样的字符串用这个临时暂存
	vector<string>s3;     //存储输出的字符串
	bool flag = false;  //是不是以"开头的字符串
	int j = s.length();
	for (int i = 0; i < j; i++) {
		if ((s[i] == ',') && (flag == true)&&(s[i+1]!='"'))  //这里以下一个不是'"'来作为结束的判断标志之一,因为这里一定不是,例如"a,"","b,""如果连在一起就没法判断。
		{
			string s4 = ""; int j3 = 0;
			j3++;   //把第一个"去了。
			int j4 = s21.size();
			for (; j3 < j4; j3++) {
				if (s21[j3] != '"') { s4 = s4 + s21[j3]; }  //非"直接加
				else if ((j3 + 2 < j4) && (s21[j3 + 1] == '"')) {
					s4 = s4 + s21[j3];  //只有这一种情况下是作为输出字符的,其他情况下都是作为转义字符或是结束字符的。
				}
				else if ((s21[j3] == '"') && (s21[j3 - 1] == ',') && (j3 + 1 >= j4)) { cout << "error" << endl; return 0; }
			}
			s21.clear(); flag = false;
			s3.push_back(s4);
		}
		else if ((s[i] == ',') && (flag == false))
		{
			string s4 = "";
			while (!s2.empty()) {
				s4 = s4 + s2.front();
				s2.pop();
			}
			s3.push_back(s4);
		}
		else if ((flag == false) && (s[i] != '"'))
		{
			s2.push(s[i]);
		}
		else if ((s[i] == '"') || (flag == true)) {
			flag = true;
			s21.push_back(s[i]);
		}
		if (i == j - 1) {
			if (flag == true) {
				string s4 = ""; int j3 = 0;
				j3++;   //把第一个"去了。
				int j4 = s21.size();
				for (; j3 < j4; j3++) {
					if (s21[j3] != '"') { s4 = s4 + s21[j3]; }
					else if ((j3 + 2 < j4) && (s21[j3 + 1] == '"')) {
						s4 = s4 + s21[j3];
					}
					else if ((s21[j3] == '"') && (s21[j3 - 1] == ',') && (j3 + 1 >= j4)) { cout << "error" << endl; return 0; }
				}
				s21.clear(); flag = false;
				s3.push_back(s4);
			}
			else {
				string s4 = "";
				while (!s2.empty()) {
					s4 = s4 + s2.front();
					s2.pop();
				}
				s3.push_back(s4);
			}
		}
	}
	//以上这个循环,前面两种是遇到了逗号,开始处理上一个字段。
	//中间的两个是把一个一个的字符输入到中间临时暂存字符串的地方去。
	//最后一个是对最后一个字段的处理。
	int j6 = s3.size();
	cout << j6 << endl;
	for (int i8 = 0; i8 < j6; i8++) {
		if (s3[i8] == "") { cout << "--" << endl; }
		else { cout << s3[i8] << endl; }
	}
	return 0;
}

这个代码自测几个数据是可以的,但是没有在机试时跑,不知道怎么样。
3.n度好友,比如说A-B-C,那么C就是A的二度好友。这里C走这条路是中间经过的中间人是最少的。就是说如果还有A-B-D-C,依然认为C是A的二度好友,即取最短的那个。
推荐值,A-B好友熟悉程度为k1(0 输入:第一行输入整数T,表示有T组测试数据(0 对于每组测试数据,输入2行,
第1行输入3个整数m,i,n分别代表用户数m,某个用户号i,n度好友,代表本组测试需要输出用户i的n度好友.
第2行输入1个整型数k,接下来3*k个整数用空格隔开,每三个组成一个关系对,每个关系由3个整型数组成i,j,w代表用户j和i的熟悉程度,即 r [ i ] [ j ] = r [ j ] [ i ] = w r[i][j]=r[j][i]=w r[i][j]=r[j][i]=w.
输出:T行,每行是每组数据对应的输出。按照推荐值降序输出,相同推荐值的,按照好友编号升序输出。如果没有n度好友,则输出-1.

#include 
#include 
#include 
using namespace std;

struct node {
	int weidu;
	int tuijian;
};

struct node1 {
	int num;  //序号
	int tuijian;//推荐值
	friend bool operator <(node1 n1, node1 n2) {  //只可以重载小于号
		if (n1.tuijian == n2.tuijian) { return n1.num > n2.num; }  //序号大的优先级小
		else { return n1.tuijian < n2.tuijian; }   //推荐值小的优先级小。
	}
};
int main() {
	int T = 0;
	cin >> T;
	while (T--) {
		int m = 0;
		int i = 0;
		int n = 0;
		int a2[100][100] = { 0 };
		cin >> m >> i >> n;  //分别表示用户数,用户编号和n度好友
		int k = 0;
		cin >> k;  //k组数据
		for (int i1 = 0; i1 < k; i1++) {
			int i4 = 0; int i5 = 0; int i6 = 0;
			cin >> i4 >> i5 >> i6;
			a2[i4][i5] = a2[i5][i4] = i6;
		}
		//输入数据
		bool b2[100] = { false };  //默认每个点都未访问。
		node b3[100];
		for (int i5 = 0; i5 < 100; i5++) {
			b3[i5].tuijian = 0;
			b3[i5].weidu = 0;
		}
		queue<int>q1;  //记录当前的上一层,打算使用广度优先先计算出每个节点的度,以及推荐值
		q1.push(i); b2[i] = true; b3[i].weidu = 0; b3[i].tuijian = 0;
		while (!q1.empty()) {
			int i8 = q1.front(); q1.pop();
			if (b3[i8].weidu == n + 1) { break; }
			for (int i9 = 0; i9 < m; i9++) {
				if ((b2[i9])&&(b3[i8].tuijian + a2[i8][i9]>b3[i9].tuijian)&&(b3[i9].weidu==b3[i8].weidu+1)) {
					b3[i9].tuijian = b3[i8].tuijian + a2[i8][i9];
				}
				if ((a2[i8][i9] > 0) && (!b2[i9])) {
					q1.push(i9);
					b2[i9] = true;
					b3[i9].weidu = b3[i8].weidu + 1;
					b3[i9].tuijian = b3[i8].tuijian + a2[i8][i9];
				}
			}
		}
		//这里这个算法,我个人觉得是一个层次遍历。
		priority_queue<node1>v1;
		for (int i12 = 0; i12 < m; i12++) {
			if (b3[i12].weidu == n) {
				node1 n3;
				n3.num = i12;
				n3.tuijian = b3[i12].tuijian;
				v1.push(n3);
			}
		}
		if (v1.empty()) { cout << "-1"; continue; }
		while (!v1.empty()) {
			cout << v1.top().num << " ";
			v1.pop();
		}
	}
	return 0;
}

这个代码也没有机试时跑,自测几个数据是可以的。有人说用栈的思想解决。但是最终还是选择了这个层次遍历的思想,
这次怕是有凉了,不知道后续会怎么样。不过前天收到一个职业性格测试,过了?再有,华为的性格测试是自己的题库,不像有的大厂,直接用的一些常用的数据库来做的,我怎么知道的?(答:我做了好多家的测试了。)
3.9更新,快两周了,没消息。应该是凉了,不报希望了。如有后续,评论区里面见。

你可能感兴趣的:(大四求职,数据结构,算法,c++)