华为3.31机试AK题解

第一题:
直接开一个26长度的结构体数组(结构体有队伍名字'a-z',得分)。然后读入字符串,按照题意计算对应的字母的得分,累加到对应数组位置上,比如'a'的对应位置是0,z是25。最后按照得分第一关键字从高到低,名字第二关键字从低到高排序就可以了。

第二题:
1.假如a说有x个人和他一样颜色,那么a的颜色至多能容纳(x+1)个人。
2.假如a说x,b说y,那么a和b的颜色一定不一样,为什么呢?举个例子,有两种颜色分别为1,2。假设分布为 1 1 2 2 2 ,其中a为1颜***为2颜色,那么a会说1,b会说2。假设b为1颜色,那么b也会说1。
3.前两点得出的结论就是说,其实每个人相当于买了一栋楼,楼里的房间个数为(x+1),自己先占了一间,然后这栋楼还可以住和他说一样的数字——也就是x的人。注满即止。如果有(x+2)个人说了x,那么就得新买一栋楼。
4.所以答案很显然了,直接求出说x的人数,然后求这些说x的人数至少得住几栋楼,那么就是  ceil (cnt(x) / (x+1))。 其中ceil是向上取整。
5.用4的方法对每个x累加即可。

第三题:
贪心是错的,暴力回溯会超时,正解是dp。
dp的话其实也有几种思路,其中一种就是评论区老哥发的leetcode上的一道类似题的官方解法https://leetcode-cn.com/problems/freedom-trail/。感兴趣的自己去看,他的复杂度是O(n^2m)的。
在这里讲下我的做法吧,复杂度是O(nm)的。
首先:用start表示游标起始位置,n表示字符数组长度,m表示匹配串长度。a表示字符数组,b表示匹配串。
1.前面的表示以及dp转移其实和leetcode题解是相似的。
2.dp[i][j]表示现在游标指在a的i位置,匹配了b的j个字符,所用的最少的移动次数。
3.初始化dp[i][j]=INF(也就是正无穷,1e7以上就行,我用的1e8)
4.那么dp[start][0] = 0。其余的dp[i][0] = min(abs(i-start),n-abs(i-start) ) 也就是向左或者向右取最小的步数。
5.转移方程:
(1) dp[i][j] = dp[i][j-1]  if a[i] == b[j] (也就是不用移动游标了,因为当前的i就可以匹配了)
(2) dp[i][j] = min(dp[i][j],dp[i+1][j])  这个i和i+1记得取模,这里就不写了
(3) dp[i][j] = min(dp[i][j],dp[i-1][j])  这个i和i-1记得取模,这里就不写了
6.过程:
  1. 枚举j
  2. 遍历a,如果a[i]==b[j],那么用(1)号方程转移
  3. 从后往前遍历两轮用(2)号方程转移
  4. 从前往后遍历两轮用(3)号方程转移
  5. 最后答案就是min dp[i][m] (i in 0 to n-1)

#笔试题目##华为#
全部评论
第三题leetcode有类似题:https://leetcode-cn.com/problems/freedom-trail/
4 回复 分享
发布于 2021-04-01 13:48
然而贪心(75)过的比暴力回溯(65)还多
2 回复 分享
发布于 2021-04-01 10:58
求题目呜呜呜
1 回复 分享
发布于 2021-04-02 17:11
复习一下,防止复试被问到 class Solution { public:     int findRotateSteps(string ring, string key) {         int m = key.size(), n = ring.size();         vector<vector<int>> pos(26, vector<int>(0, 0));         for (int i = 0; i < n; i++) {             pos[ring[i] - 'a&(417)#39;].push_back(i);         }         vector<vector<int>> dp(m, vector<int>(n, 0x3f3f3f3f));         for (auto j:pos[key[0] - 'a&(417)#39;]) {             dp[0][j] = min(j, n - j);         }         for (int i = 1; i < m; i++) {             for (auto j:pos[key[i] - 'a&(417)#39;]) {                 for (auto k:pos[key[i - 1] - 'a&(417)#39;]) {                     dp[i][j] = min(dp[i][j], dp[i - 1][k] + min(abs(k - j), n - abs(k - j)));                 }             }         }         int min = INT_MAX;         for (auto item:dp[m - 1]) {             if (item < min) {                 min = item;             }         }         return min + m;     } };
1 回复 分享
发布于 2021-04-11 23:05
第三题确实不会用dp😂坐等大佬更新😁
点赞 回复 分享
发布于 2021-04-01 05:01
等大佬更新
点赞 回复 分享
发布于 2021-04-01 09:10
坐等大佬解第三题,dp真的好难
点赞 回复 分享
发布于 2021-04-01 09:35
点赞 回复 分享
发布于 2021-04-01 10:59
感觉回溯剪枝了有可能过 `int traceback(int cur , int bushu , int now){// 当前所在点, 已经走了多少步 ,即将要匹配pat中的哪一个` 1. 如果准备匹配的字符是唯一的,毋庸置疑往左或者往右找最短的就是唯一路径 2.如果匹配的字符不是唯一的,不能所有点都开回溯(极端例子,主串abbbbbbbbbbbq, 目标串abq),只需要开2个点的回溯就可以了,一个向右走一个向左走。(这里剪枝了很多) 但是硬算时间复杂度还是过不了的(指数级别),似乎华为样例没有很严格 白给白给
点赞 回复 分享
发布于 2021-04-01 11:03
第1题知道怎么做,但是样例2没看懂,求个解答 a-b 3:0 a-c 2:1 b-a 1:1 c-a 0:1 b-c 4:3 c-b 2:2 输出是:a 10,b 5,c 1 搞不明白,
点赞 回复 分享
发布于 2021-04-02 10:19
第二题跟楼主一个思路,没过,其他ac了
点赞 回复 分享
发布于 2021-04-02 20:33
好厉害啊,你是华工计院/软院大佬吗
点赞 回复 分享
发布于 2021-04-03 12:25
最后一题对i和i-1取模是什么意思?
点赞 回复 分享
发布于 2021-04-07 16:30

相关推荐

CISYA:啊?这么溜的简历会难?
点赞 评论 收藏
分享
10 58 评论
分享
牛客网
牛客企业服务