[算法笔试题]华为相关复习题(更新中)

算法笔试题 华为相关复习题

笔试题目1

  • leetcode 698. 划分为k个相等的子集
    题目链接:划分为k个相等的子集
    使用概念:回溯+剪枝
    代码链接:python代码

笔试题目2

统计频率

输入一串数字,统计每个数字出现的次数,然后按照出现次数降序排列,如果出现次数一样,则按照数字第一出现的下标升序排列。

类似练习

  • leetcode 347. 前 K 个高频元素
    题目链接:前 K 个高频元素
    代码链接:python代码
    重要的操作就是以下两个
    默认字典和字典排序
number[n] = number.get(n,0) + 1
data = (sorted(number.items(),key = lambda x:x[1],reverse = True))[:k]

寻找第K大/小的元素

  • leetcode 215. 数组中的第K个最大元素
    题目链接:数组中的第K个最大元素
    代码链接:python代码

更麻烦一点的情况是处理字符串的时候

输入一个由 n 个大小写字母组成的字符串,按照 Ascii 码值从小到大的排序规则,查找字符串中第 k 个最小ascii 码值的字母(k >= 1),输出该字母所在字符串的位置索引(字符串的第一个字符位置索引为 0)。
k 如果大于字符串长度,则输出最大 ascii 值的字母所在字符串的位置索引,如果有重复的字母,则输出字母的最小位置索引。

输入描述:

第一行输入一个由大小写字母组成的字符串
第二行输入 k,k 必须大于 0,k 可以大于输入字符串的长度

输出描述:

输出字符串中第 k 个最小 ascii 码值的字母所在字符串的位置索引。k 如果大于字符串长度,则输出最大 ascii 值的字母所
在字符串的位置索引,如果第 k 个最小 ascii 码 值的字母存在重复,则输出该字母的最小位置索引。

示例 1:

输入 AbCdeFG 3
输出 5

稍微修改了一下代码即可获得

nums = 'AbCdeFG'
nums = list(nums)
temp = nums[::]
length = len(nums)
k = 3
k -= 1 
def quick_sort(nums,left,right):
    bound = nums[left]
    i,j = left,right
    while(i<j):
        while(i<j and nums[j] >= bound):
            j -= 1
        nums[i] = nums[j]
        while(i<j and nums[i]<=bound):
            i += 1
        nums[j] = nums[i]
    nums[i] = bound
    return i
index = quick_sort(nums,0,length-1)
while(index != k):
    if index > k:
        index = quick_sort(nums,0,index-1)
    elif index < k:
        index = quick_sort(nums,index+1,length-1)
target = nums[k]
print(temp.index(target))

笔试题目3

在给定矩阵的字符下,寻找存在某字符串的路径,如果存在就返回开始的下标。

类似练习

  • leetcode 79. 单词搜索
    题目链接:单词搜索
    代码链接:python代码

笔试题目4 迷宫问题

输入: m,n,表示一个m*n的网格
begin坐标,end坐标
障碍物个数i:i个障碍物的坐标
找到begin到end最短路径的长度,如果有多个最短路径,还要输出最短路径个数

类似练习

  • 牛客 地下迷宫(广度优先)
    题目链接:地下迷宫
    代码链接:python代码

笔试题目5 寻找重复子树

按照层序遍历的顺序给你一个树,找到这个数里的重复子树,如果有多个重复子树就输出最高的树的层序遍历

类似练习

  • leetcode 652. 寻找重复的子树
    题目链接:寻找重复的子树
    代码链接:python代码

笔试题目6 括号深度

计算带‘{},[],()’的有效括号的最大深度。

类似练习

  • leetcode 32 最长有效括号
    题目链接:最长有效括号
    代码链接:python代码
  • leetcode 22 括号生成
    题目链接:括号生成
    代码链接:python代码

笔试题目7 找顺子

真题链接:斗地主之顺子

类似练习

  • 剑指 Offer 61. 扑克牌中的顺子
    题目链接:扑克牌中的顺子
  • leetcode 846. 一手顺子
    题目链接:一手顺子
    这两题的难度相比还是简单了一些
    随手写了一个看起来不太好看的代码
from collections import Counter
joker = [5,6,7,8,9,12,13,1,2,3,4,10,11,3,4,5,6,3,2,6,7,8,9]
hand = Counter(joker)
res = []
for i in [1,2]:
    if i in hand.keys():
        hand.pop(i)


for start in sorted(hand.keys()):
    while(hand[start] > 0):
        line = []
        for end in range(start,15):
            if hand[end] < 1:
                break
            hand[end] -= 1
            line.append(end)
        if len(line) >= 5:
            res.append(line)
        else:
            break
print(res)
        

笔试题目8 检测IP地址

类似练习

  • 牛客BM85 验证IP地址
    题目链接:验证IP地址
    代码链接:python代码

  • 牛客HJ39 判断两个IP是否属于同一子网
    题目链接:判断两个IP是否属于同一子网

笔试题目9 有向无环图

类似练习

  • leetcode 207 课程表
    题目链接:课程表

  • leetcode 210 课程表 II
    题目链接:课程表
    代码链接:python代码

  • leetcode 630 课程表 III
    题目链接:课程表
    代码链接:python代码

  • 服务器依赖

假设服务器aM依赖于服务器aN, 用aM-aN表示, 并且这种依赖关系可以传递, 服务器总数量小于3000.
现有一些列的服务器依赖关系和损坏的服务器, 编程升序输出所有可以正常工作的服务器,
输入输出格式严格按照下面示例, 输入依赖aM-aN间以逗号分隔,第二行为损坏的服务器,也以逗号分隔, 第三行输出正常的服务器, 以逗号分隔.

输入示例: a1-a2,a3-a4,a5-a1,a4-a6 a2
输出 a3,a4,a6

没想到特别好的方法先用回溯法写了一个
看到大佬用冒牌排序法写了感觉很牛但是没学会phhh

service = 'a1-a2,a3-a4,a5-a1,a4-a6'
service = service.split(',')
broke = [4,5]
machine = {}
N = 6
state = [True for _ in range(N)]
for s in service:
    sub,main = s.split('-')
    sub,main = int(sub[1:])-1,int(main[1:])-1
    if main not in machine.keys():
        machine[main]=set()
    machine[main].add(sub)
    
def dfs(b):
    state[b] = False
    if b not in machine.keys():return
    for p in machine[b]:
        dfs(p)
    return
for b in broke:
    dfs(b-1)
res = []
for n in range(N):
    if state[n]:
        res.append('a'+str(n+1))
print(','.join(res))




笔试题目10 接雨水

  • leetcode 42 接雨水
    题目链接:接雨水
    代码链接:python代码
  • leetcode 407 接雨水 II
    题目链接:接雨水 II
    代码链接:python代码

笔试题目11 最长数字字符字串

[编程|100分] 在字符串中找出连续最长的数字串

时间限制:3秒

空间限制:32768K

题目描述

请一个在字符串中找出连续最长的数字串,并把这个串的长度返回;如果存在长度相同的连续数字串,返回最后一个连续数字串;

注意:数字串只需要是数字组成的就可以,并不要求顺序,比如数字串“1234”的长度就小于数字串“1359055”,如果没有数字,则返回空字符串(“”)而不是NULL!(说明:不需要考虑负数)

输入描述:

字符串输出描述:

连续数字串&在所有数字串最长的长度

示例1

输入:abcd12345ed125ss123058789

输出:123058789

来源:原文链接

s = 'abcd12345ed125ss123058789'
length = len(s)
local_max,global_max = 0,0
result = 0
for l in range(length):
    if '0' <= s[l] <= '9':
        local_max += 1
        if local_max > global_max:
            global_max = local_max
            result = l-global_max+1
    else:
        local_max = 0
        
print(s[result:result+global_max+1])

强化练习 深度优先算法

强化练习 回溯/递归

  • leetcode 46&47 全排列
    题目链接:全排列

笔试题目12 报数游戏

时间限制:3秒

空间限制:32768K

题目描述

100个人围成一圈,每个人有一个编码,编号从1开始到100。他们从1开始依次报数,报到为M的人自动退出圈圈,然后下一个人接着从1开始报数,直到剩余的人数小于M。请问最后剩余的人在原先的编号为多少? 例如输入M=3时,输出为: “58,91” ,输入M=4时,输出为: “34,45,97”。

这个是基础的约瑟夫环问题
主要难点在于推导映射
leetcode1823 有原题

N,M = 100,3
index = [i for i in range(1,M)]
for n in range(N-M+1):#转化N-M+1次
    for i in range(M-1):#对剩下的M-1个数进行处理
        if index[i] <= n:#映射
            index[i] = index[i] + M
        else:
            index[i] = (index[i] - n)

index.sort()
print(index)
    

来源:原文链接

笔试题目13 字符串处理

  • 交换一次得到最小字符串
    题目描述:

给定一个字符串s,最多只能进行一次变换,返回变换后能得到的最小字符串(按照字典序进行比较)。
变换规则:交换字符串中任意两个不同位置的字符。

输入描述: 一串小写字母组成的字符串s
输出描述:按照要求进行变换得到的最小字符串

string = 'bcdefa'
string = list(string)
length = len(string)
for l in range(length):
    if l > 0 and string[l] == string[l-1]: continue
    min_element = min(string[l:])
    if string[l] == min_element:
        continue
    i = string.index(min_element,l)
    string[l],string[i] = string[i],string[l]
    break
print(''.join(string))

示例

输入:abcdef
输出:abcdef
说明:abcdef已经是最小字符串,不需要交换
输入: bcdefa
输出:acdefb
说明:a和b进行位置交换,可以得到最小字符串

真题复盘

服务器调度 优先级排序

这题其实很简单 python调用sort函数排序即可
只需要添加一些判断条件
qwq最大的问题在于题目很长
状态不太好没有专心看题
漏看了条件最后才发现
同时输出需要按序号排序而不是优先级队列里的排序
…没有按照要求输出真的无语

分糖果

现有若干袋糖果,想把这些糖果平分给两个小朋友,每袋糖果只能分给一个小朋友且不能拆开,返回每个小朋友分得的糖果数,每个小朋友分到的各袋糖果的糖果数,输出顺序不限,如不能平均分则直接输出-1
输入为每袋糖果的糖果数量
例:

输入:

3 5 7 2 5 8

输出:

15
7 8
3 5 2 5

这题跟上面的分为k个子集其实是一样的
当时过于紧张了qwq没能完成题目
心情很不好
看到很多人也评论说写出来了最后也只过了5%
虽然很悲伤还是在这里把没能写出来的代码写出来
该方法烦人的地方在于要把数组的分组情况也呈现出来

动态规划

这两题应该是相似的(明明是写过的题)
唯一不一样的是leecode416只需要输出能否分割即可
这里需要输出分割结果
但是这个方法我存疑的地方在于
如果数组中数字较大
记录动态规划的表格会不会过大
造成一定的浪费
这时使用回溯法穷尽不失为一种好方法

nums = [5,3,7,2,5,4,4,8,33,11,11,11] 
def canPartition(nums):
    res = [[],[]]
    total = sum(nums)
    if total % 2 > 0: return False
    sub,m = (total // 2),len(nums)
    state = [[[False,(-1,0)] for _ in range(sub+1)] for _ in range(m)]
    for i in range(m):
        state[i][0] = [True,(-1,0)]
        
    for i in range(1,m):
        for j in range(sub+1):
            if state[i-1][j][0]:
                state[i][j] = [True,(i-1,j)]
            elif nums[i] <= j and state[i-1][j-nums[i]][0]:
                state[i][j] = [True,(i-1,j-nums[i])]
    if state[-1][-1]:
        x,y = m-1,sub
        res = [[],[]]
        while(x>=0):
            xx,yy = state[x][y][1]
            if yy == y:
                res[1].append(nums[x])
            else:
                res[0].append(nums[x])
            x,y = xx,yy
        print(res)
        return True
    else:
        print(-1)
        return False
            

    
state = canPartition(nums)

回溯法

稍微修改一下leetcode698的代码可以获得
但是没有经过系统测试
只是使用了给的一个算例验证

nums = [3,5,7,2,5,8] 
res = [[],[]]

def canPartitionKSubsets(nums):
    k,total = 2,sum(nums)
    if total % k > 0:return False #检查能否分组
    target = total // k
    nums.sort()#数组排序
    if nums[-1] > target: return False #如果最大值高于平均值没有必要分组
    sums = [0 for _ in range(k)]
    def split_fun(sums):
        if not nums:return True
        n = nums.pop()
        for j in range(k):
            if sums[j] + n >target:
                continue
            sums[j] += n
            res[j].append(str(n))
            if split_fun(sums):
                return True
            else:
                sums[j] -= n
                res[j].pop()
        nums.append(n)
        return False
    return split_fun(sums)
if not canPartitionKSubsets(nums):
    print(-1)
else:
    for i in range(2):
        print(' '.join(res[i]))
    

总而言之,都是旧的知识点
没写出来真的很伤心

任务调度 贪心+优先级队列

输入若干工单,每个包含SLA时间和score,即在规定SLA时间内完成该工单可以获得对应score,超时不得分,每个工单需要一个小时来完成,返回可以获得的最大得分
例:

输入:
7
1 6
1 7
3 2
3 1
2 4
2 5
6 1
输出: 15(完成第2,6,3,7个工单)

悲伤逆流成河
这题用python实现只需要不到二十行代码
就能实现了
首先熟悉了一下类似的题型leetcode 630 课程表 III
稍微修改一下代码就能得到如下结果

import heapq
N = 7
task = [[1,6],[1,7],[3,2],[3,1],[2,4],[2,5],[6,1]]
time = 1
task = sorted(task,key = lambda x:x[0])
pq = []
for t in task:
    if time > t[0] and t[1] > pq[0]:
        heapq.heappop(pq)
        time -= 1
    if time <= t[0]:
        heapq.heappush(pq,t[1])
        time += 1
print(sum(pq))

原题链接

你可能感兴趣的:(丁丁的Python学习笔记,python)