华为2021笔试记录

重复一次的最长子串

在一个字符串中找到最多重复一次的最长子串,并返回子串长度(AC100%)

输入:abcabcbb
输出:6
说明:abcabc是最多重复一次的最长子串

  • 该题是3. 无重复字符的最长子串的变体,利用滑动窗口思想,不断更新左右指针,
    • 右指针向右跳,并更新窗口的内容
    • 若满足while window[c]>2,说明该字符开始重复第3次,不满足条件了,因此左指针开始向右跳,并更新窗口内容
s=list(map(str,input().strip().split()))
s=",".join(s)
from collections import defaultdict
window=defaultdict(int)
l,r=0,0
res_max=0
while r<len(s):
    c=s[r]
    r+=1
    window[c]+=1

    while window[c]>2:
        d=s[l]
        l+=1
        window[d]-=1
    res_max=max(res_max,r-l)
print(res_max)

先按照年月日排序,年月日相同时按照姓名排序,输出姓名

输入:2
zhang san, 1990,1,1
lisi,1991,2,2

输出:zhang san, li si

AC 50%

n=int(input())
if n<=0:
    print()

res=[]
for i in range(n):
    # res.append(input())
    res.append(list(map(str,input().strip().split(', '))))
# print(res)
ans=sorted(res,key=lambda x:(x[1],x[2],x[3],x[0]))
# print(ans)
name=[i[0] for i in ans]
name=", ".join(name)
print(name)

# 2
# zhang san, 1985, 12, 31
# li si, 1977, 9, 1
#include <vector>
#include <iostream>
#include <sstream>
#include <algorithm>

using namespace std;

int main() {
    int n;
    cin >> n;
    cin.get(); // 要加这一行,以“吸收”n后面的回车
    string line;
    string item;
    // 构建二维数组
    vector<vector<string>> vec;
    for (int i = 0; i < n; ++i) {
        getline(cin, line);
        stringstream ss(line);
        vector<string> tmp;
        while (getline(ss, item, ', ')) {
            tmp.push_back(item);
        }
        vec.push_back(tmp);
    }

    // lambda函数进行排序,并保存结果
    vector<string> res;
    sort(vec.begin(), vec.end(), [](vector<string> &a, vector<string> &b) {
        if (a[3] == b[3]) return a[0] < b[0];
        if (a[2] == b[2]) return a[3] < b[3];
        if (a[1] == b[1]) return a[2] < b[2];
        return a[1] < b[1];
    });
    for (auto &i : vec) {
        res.push_back(i[0]);
    }

    // 打印结果
    for (int i = 0; i < res.size(); ++i) {
        cout << res[i];
        if (i!=res.size()-1){
            cout<<", ";
        }
    }
}

字符串除法

计算第一个字符串中有几个第二个字符串。无需考虑字符串顺序(不知道AC多少)

输入:abcdabcdab bcae
输出:0 (e不在第一个字符串中)
输入:abcdabcdab bca
输出:2 (第一个字符串中有3个b,2个c,3个a。因此第一个字符串中能找到2个第二个字符串)

a,b=list(map(str,input().strip().split()))
from collections import defaultdict
da=defaultdict(int)
db=defaultdict(int)

for i in a:
    da[i]+=1
for i in b:
    db[i]+=1

# print(da)
# print(db)

res=[]
flag=-1# flag若始终为-1说明b中的key都能在a中找到
for i in db:
    if i in da:
        tmp=da[i]//db[i]
        res.append(tmp) # a中各元素中 有几倍的 b中各元素
    else:
        flag=0# 若b中的key在a中找不到,则改变flag的值

print(min(res) if flag==-1 else 0)

输出相同或连续子串的个数

如子串 “11121”中,”111” 1个, “11” 2个,”1” 4个, “2” 1个,总共8个

AC 100%

  • i从第0个位置遍历到倒数第二个位置,j从i+1处开始遍历
    • 若i和j对应的元素相同,则计数+1。否则跳出j的循环,开始下一次i的循环
  • 遍历结束后加上最后一个元素
s=str(input())
nums=0
l=len(s)
# i遍历到倒数第二个位置,j从i+1处开始遍历
for i in range(len(s)-1):
    nums+=1 #每经过一个元素,+1 
    x=s[i]
    for j in range(i+1,len(s)):
        if s[j]==x: # 后面每连续一次,+1
            nums+=1
        else: # 若不连续,则跳出
            break
nums+=1 # 加上最后一个元素
print(nums)

天平平衡

有一堆砝码,天平平衡时,砝码一侧的最大值是多少?

有数组[1,2,3,6]。平衡时,一侧放[1,2,3],另一侧放[6]。结果输出6

背包问题的变体,有点像 LeetCode 416. 分割等和子集。

目前只AC 80% (如[1,2,3,7]这种数组,结果就不对),应该是状态转移方程这里有问题。

nums=list(map(int,input().strip().split(',')))
import math
total=math.floor(sum(nums)/2)
if len(nums)<2:
    print(0)
else:
    n=len(nums)
    dp=[[0 for _ in range(total+1)] for _ in range(n+1)]
    for i in range(1,n+1):
        for j in range(1,total+1):
            if j<nums[i-1]:
                dp[i][j]=dp[i-1][j]# 物品太大,超过容量了,装不下
            else:
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-nums[i-1]]+nums[i-1])# 装或不装的最大值
    print(dp)
    print(dp[-1][-1])

小测试

n的阶乘末尾含0的个数

  • 能生成0,肯定是2*5的组合,其中,2(以及2的倍数)比5的多,所以只要看有几个5
  • 25(5*5),125(5*5*5)这种组合,有多个5。所以要不断更新n

产生零的条件

要在末尾产生0,则必然是5×2,即使是原数中包含的0也可以分解,因此将题目简化为寻找阶乘中5的个数,即n//5,但是要考虑到这只找到了n中是5倍数的所有数,例如25,即在25!中找到了5个是5的倍数的数分别为5,10,15,20,25,要注意这之中的25依然可以分解为5的倍数,因此n//5其实是少计入了一部分情况的。

要对接下来的这部分情况进行统计,我们可以对n取25的商,即n//25,这样就找到了包含有2个5的数(且因为是对5×5取商,没有重复计入),依此类推,可以循环对n取5, 25, 125…的商,将所有的情况都包括,最终将所有的商汇总即0的个数。

n // 25 == n // 5 // 5,因此可以对n循环取5的商,其效果是一样的。

class Solution:
    def trailingZeroes(self, n):
        num = 0
        while n > 0:
            num += n // 5 # 找到5的倍数
            n = n // 5 # 重新更新n,继续找,直到没有5的倍数
        return num

不要算出阶乘的结果后才统计(以下方法不推荐)

n=int(input())+1
dp=[1 for i in range(n)]
for i in range(1,n):
    dp[i]=dp[i-1]*i
res=dp[-1]
res=str(res)
count=0
for j in range(len(res)-1,-1,-1):
    if res[j]=='0':
        count+=1
    else:
        break
print(count)

   转载规则


《华为2021笔试记录》 M 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
第一章:手把手带你刷二叉树-第二期 第一章:手把手带你刷二叉树-第二期
labuladong 手把手带你刷二叉树(第二期) 654. 最大二叉树递归结束条件:nums中没有元素明确函数的定义(但不跳进递归去):找到最大值及最大值的索引,并根据索引将其分成左右两个子nums集合左右子树递归调用该函数 # Defi
2021-03-18
下一篇 
第零章:手把手带你刷二叉树(第一期) 第零章:手把手带你刷二叉树(第一期)
labuladong 手把手带你刷二叉树(第一期) 递归算法的关键要明确函数的定义,相信这个定义,而不要跳进递归细节递归结束的条件一定要写,否则递归跳不出来写二叉树的算法题,都是基于递归框架的(只要涉及递归,都可以抽象成二叉树的问题),我
2021-02-28
  目录