华为OD机试为什么会挂那么多?
最近一段时间,发现华为OD的机试总是很多人都挂掉,很多人得0分我就认为是平台不会用,或者直接放弃了。
但有些人只考了十几分、几十分,我就想不通了,题到底有多难呢?
抱着这个疑问,我也申请了一次机考,并于2022年2月1号的凌晨把它给做了。
下面说一下我的经验。
设备:
机考需要防作弊,所以需要一台有摄像头的电脑。
考试期间,需要让屏幕处于录制状态,手机也要扫一个二维码,并保持在那个界面不动。
我是没有带摄像头的电脑的,但我有个笔记本。笔记本有摄像头,但键盘和屏幕不适合敲代码。于是:
我把笔记本当摄像头和主机,外接了一个屏幕和一个键盘。
手机充上电,因为是凌晨,并且正好是大过年的 ,不会有人给我打电话。
开始之前:
有好几个步骤要点,比如签名啊、启动监控啊之类的。
一切就绪,开考:
首先是一个例子,输入两个数字 a和b,让你求 a+b 。 刚开始我没看明白,以为题目这么简单吗? 思考了十分钟,才发现它是一个例子。
第一题,【非严格递增连续数字序列】
大概是给你一个字符串,长度题目好像给了, 最大不超过255个字符(这就看出来,暴力就行,不需要花里胡哨的算法),让你找出最长的一个连续的数字(要求非严格递增,即 12234 这种,递增但不要求严格递增,但不能递减),比如 abasdf12234sdaf112 , 最长连续数字是 12234,长度是5,让你返回这个长度。
这个太简单了,直接暴力解决,AC了。
我的代码(满分,做题用时 7分24秒):
#include <string> #include <iostream> #include <stdlib.h> using namespace std; bool isNum(char c) { return c >= '0' && c <= '9'; } int main() { string str; cin >> str; if (str.size() == 0) { return 0; } int maxlen = -1; for (int i = 0; i < str.length(); i++) { if (isNum(str[i])) { maxlen = max(maxlen,1); int tmplen = 1; for (int j = i+1; j < str.length(); j++) { if (isNum(str[j]) && str[j] >= str[j-1]) { tmplen++; } else { break; } } maxlen = max(maxlen, tmplen); } } if (maxlen == -1) { maxlen = 0; } cout << maxlen << endl; return 0; }
第二题,【查找众数及中位数】
题目很复杂,先给出一个 众数 的概念,就是数组中出现次数最多的数字。
又给出一个 中位数的概念,就是从小到大排序后,中间那个数。如果数组大小是偶数,则取中间两个相加再除以2.
让求 给定的数组中的众数, 如果有多个,就把众数组成一个新的数组,求新数组的中位数。
这道题我在输入的时候,就把数组搞了个map,以数字做key,出现的次数做value,并用一个临时变量记录最大的 value。
然后再从数组中找出value等于这个 maxvalue 的 key,放入一个vector。因为map本身就是排过序的,所以不用对vector再排序了。
然后看下vector的大小,是偶数的话,取 中间两个相加除以2, 是奇数的话,直接返回中间那个,搞定了。
这个方法并不是最优解,但能过就行。
我的代码(满分,做题用时 11分17秒)
#include <string> #include <iostream> #include <stdlib.h> #include <map> #include <vector> #include <utility> using namespace std; int main() { map<int,int> colects; int n = 0; int maxNum = 0; while (cin>>n) { auto it = colects.find(n); if (it != colects.end()) { it->second++; maxNum = max(maxNum, it->second); } else { colects.insert(std::make_pair(n, 1)); maxNum = max(maxNum, 1); } } vector<int> middles; for (auto it = colects.begin(); it != colects.end(); it++) { if (it->second == maxNum) { middles.push_back(it->first); } } if (middles.size()%2) { cout << middles[middles.size() / 2] << endl; } else { cout << (middles[middles.size() / 2 - 1] + middles[middles.size() / 2]) / 2 << endl; } return 0; }
第三题:【考古学家 】
有一大堆墓碑碎片,每个碎片就是一个字符串,让你给出排列组合的所有可能,要去重。
比如 a b c 这么3块墓碑,排列组合有:
abc acb bac bca cab cba 这么多种。
比如 墓碑是 a b ab ,则 要记得去重,结果是 abab aabb baab baba abba , 其实还有一个 abab,因为和第一个重了,所以要去掉。加粗的是 那个连着的 ab 。
这个就暴力,用递归就可以了。
我的代码(满分,做题用时27分6秒)
#include <string> #include <iostream> #include <stdlib.h> #include <map> #include <vector> #include <utility> #include <algorithm> using namespace std; bool checkAnyNoVisited(vector<int> &visited) { bool n = true; for_each(visited.begin(), visited.end(), [&](int x) { n &= x;}); return n; } void function(vector<string> &colects, map<string, bool> &result, string & str, vector<int> &visited) { //如果尚有未访问的,则继续,否则push到map里 if (!checkAnyNoVisited(visited)) { for (int i = 0; i < colects.size(); i++) { if (visited[i] == 0) { visited[i] = 1; string tempstr = str + colects[i]; function(colects, result, tempstr, visited); visited[i] = 0; } } } else { result.insert(std::make_pair(str, true)); } return; }; int main() { int n; vector<string> colects; cin >> n; while (n) { n--; string s; cin >> s; colects.push_back(s); } map<string, bool> result; for (int i = 0; i < colects.size(); i++) { vector<int> visited(colects.size(), 0); visited[i] = 1; string str = colects[i]; function(colects, result, str, visited); visited[i] = 0; } for (auto it = result.begin(); it != result.end(); it++) { cout << it->first << endl; } return 0; }
感慨:
感觉三道题都很简单,我用了一小时十分钟。
很多题目已经给出了 一些入参的边界,我发现边界都不是很极端,好多东西都可以暴力解决。
最后打个广告:
顺便打个广告:招人,华为云计算, OD岗, 戳:
https://nowpick.nowcoder.com/w/fulltime/detail?jobId=77168
https://nowpick.nowcoder.com/w/fulltime/detail?jobId=77636
https://nowpick.nowcoder.com/w/fulltime/detail?jobId=77636