华为机试HJ1~HJ20

来源:牛客网

目录

HJ1 字符串最后一个单词的长度

HJ2 计算某字符出现次数

HJ3 明明的随机数

HJ4 字符串分隔

HJ5 进制转换

HJ6 质数因子

HJ7 取近似值

HJ8 合并表记录

HJ9 提取不重复的整数

HJ10 字符个数统计

HJ11 数字颠倒

HJ12 字符串反转

HJ13 句子逆序

HJ14 字符串排序

HJ15 求int型正整数在内存中存储时1的个数

HJ16 购物单

HJ17 坐标移动

HJ18 识别有效的IP地址和掩码并进行分类统计

HJ19 简单错误记录 

 HJ20 密码验证合格程序​​​​​​​

  • HJ1 字符串最后一个单词的长度

import sys

str = input()        #输入字符串str
arr = str.split(" ") #以空格分割字符串并将结果存入数组arr  ['hello', 'world']
n = len(arr) - 1     #获取数组最后一个元素的索引
print(len(arr[n]))   #打印最后一个元素arr[n]的长度即为最后一个单词的长度

 

 

  • HJ2 计算某字符出现次数

哈希:Hash,一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。

st1 = input().lower()   #lower() 小写函数  upper()大写函数
st2 = input().lower()
print(st1.count(st2))  #count()返回子字符串sub in不重叠出现的次数
  • HJ3 明明的随机数

while True:
    try:
        n = int(input())
        set1 = set()  #去重 构建唯一元素的无序集合
        for i in range(n):
            set1.add(int(input())) #将新输入的数添加到set1中

        nums = list(set1) #转换成list 列表
        nums.sort()     #list的sort函数排序
        for i in nums:
            print(i)
    except:
        break
  • HJ4 字符串分隔

while True:
    try:
        l = input()
        for i in range(0, len(l),8):  #range(起,始,步长)
            print("{:0<8s}".format(l[i:i + 8 ]))   #s[i:j] 表示获取a[i]到a[j-1]
    except:
        break

        # :0:数字补0(填充右边)
        # < :左对齐
        # 8s:占位符8位
        # :0 < 8s右补零,左对齐,占8位
  • HJ5 进制转换

'''
python将16进制转为10进制可以用int('hex型',16) 八进制转十进制int('八进制型',8) 八进制或十六进制或10进制装二进制直接调用 bin(任意进制)
'''
while True:
    try:
        s=input()
        s10=int(s,16)
        # s2=bin(s10)
        print(s10)
        # print(s2)
        # print(s2[2:])
    except:
        break
  • HJ6 质数因子

def get_str(num):
    i = 2
    res = []
    while num >= i * i:
        while num % i == 0:
            num = num // i  # 整除
            res.append(str(i))
        i = i + 1
    if num > 1:
        res.append(str(num))
    return ' '.join(res)   # 字符串才能用join   Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'

while True:
    try:
        print(get_str(int(input())))
    except:
        break
  • HJ7 取近似值

def fun(num_str):
    num =float(num_str)
    return int(num+0.5)

while True:
    try:
        print(fun(input()))
    except:
        break
  • HJ8 合并表记录

 

 

n = input()
dic = dict()
for i in range(int(n)):     # n循环多少次
    line = input().split()  # 空格进行分割 key value
    key = int(line[0])
    value = int(line[1])
    dic[key] = dic.get(key, 0) + value  # dic.get()   dic[key] 都是用来获取字典中 key 对应的 value
                                                # dic.get(key, 0)  0代表无key则返回0

for i in sorted(dic.keys()):        # 返回一个新列表,按升序排列。
    print(i, dic[i])
  • HJ9 提取不重复的整数

list1 = list(input()[::-1])   # -1 逆序 从右向左的阅读顺序
list2 = list(set(list1))
list2.sort(key = list1.index)  # 排序 key = list1.index 使list2按照list1元素出现的顺序进行排序(也就是原来的顺序)
print(''.join(list2))
  • HJ10 字符个数统计

while True:
    try:
        str = ''.join(set(input()))  #去重后字符串形式
        # print(str)
        count = 0
        for i in str:
            if 0 <= ord(i) <= 127:      #返回单字符字符串的Unicode码位
                count += 1
        print(count)
    except:
        break
  • HJ11 数字颠倒

str=str(input()[::-1])
print(str)
  • HJ12 字符串反转

 

str=(input()[::-1])
print(str)
  • HJ13 句子逆序

while True:
    try:
        str1 =list(input().split())  #返回字符串中的单词列表,使用sep作为分隔符字符串。
        print(' '.join(str1[::-1]))
    except:
        break
  • HJ14 字符串排序

 

  • 描述

sorted() 函数对所有可迭代的对象进行排序操作。

  • sort 与 sorted 区别:

sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。

  • 语法—sorted 语法:

sorted(iterable, key=None, reverse=False)

  • 参数说明:

iterable : 可迭代对象。
key : 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
reverse : 排序规则,reverse = True 降序 , reverse = False 升序(默认)。

  • 返回值

返回重新排序的列表。

while True:
    try:
        num=int(input())
        stack=[]
        for i in range(num):
            stack.append(input())
        print("\n".join(sorted(stack)))
    except:
        break
  • HJ15 求int型正整数在内存中存储时1的个数

while True:
    try:
        n = bin(int(input()))
        num = str(n)
        count = 0
        for i in num:
            if i == '1':
                count = count + 1
        print(count)

    except:
        break
  • HJ16 购物单

其实这题就是0-1背包问题

首先来看一下经典背包问题,稍作修改就可以得出这题的解答

0-1背包问题

问题描述:有一个背包可以装物品的总重量为W,现有N个物品,每个物品中w[i],价值v[i],用背包装物品,能装的最大价值是多少?

定义状态转移数组dp[i][j],表示前i个物品,背包重量为j的情况下能装的最大价值。

例如,dp[3][4]=6,表示用前3个物品装入重量为4的背包所能获得的最大价值为6,此时并不是3个物品全部装入,而是3个物品满足装入背包的条件下的最大价值。

状态转移方程:

dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])

dp[i-1][j]表示当前物品不放入背包,dp[i-1][j-w[i]]+v[i]表示当前物品放入背包,即当前第i个物品要么放入背包,要么不放入背包

1

2

3

4

5

6

7

8

dp = [[0]*(n+1for _ in range(m+1)]

for i in range(1,m+1):

    for j in range(1,n+1):

        if j-w[i]>=0:

            dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])

        else:

            dp[i][j] = dp[i-1][j]

return dp[m][n]

现在来看下购物车的解题思路

购物车本质上还是0-1背包问题,只不过多了主件和附件。假设先不看附件,那么就和0-1背包一样了。附件不能单独出现,要依赖于主件。

对应于背包问题,主件的个数就是物品的个数,考虑每个主件时要考虑可能出现的情况。

输入例子:
1000 5
800 2 0
400 5 1
300 5 1
400 3 0
500 2 0

在当前的例子当中物品的个数就是3。

考虑每个物品时要考虑每种可能出现的情况,1、主件,2、主件+附件1,3、主件+附件2,4、主件+附件1+附件2,不一定每种情况都出现,只有当存在附件时才会出现对应的情况。

w[i][k]表示第i个物品的第k种情况,k的取值范围0~3,分别对应以上4中情况,v[i][k]表示第i个物品对应第k种情况的价值,现在就把购物车问题转化为了0-1背包问题。

状态转移方程可以定义为

dp[i][j] = max(dp[i-1][j],dp[i-1][j-w[i][k]]+v[i][k])

dp[i-1][j]表示当前物品不放入背包,w[i][k]表示第i个主件对应第k中情况,即当前第i个物品的4中情况中价值最大的要么放入背包,要么不放入背包

需要注意:dp[i][j] = max(物品不放入背包,主件,主件+附件1,主件+附件2,主件+附件1+附件2)

1

2

3

4

5

6

7

8

9

dp = [[0]*(n+1for _ in range(m+1)]

for i in range(1,m+1):

    for j in range(1,n+1):

        max_i = dp[i-1][j]

        for k in range(len(w[i])):

            if j-w[i][k]>=0:

                max_i = max(max_i, dp[i-1][j-w[i][k]]+v[i][k])

        dp[i][j] = max_i

print(dp[m][n])

具体代码如下:

python中的map函数

回顾下状态转移方程:
dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i])

dp[i]只依赖dp[i-1],状态转移方程就可以改为:
dp[j] = max(dp_pre[j], dp_pre[j-w[i]]+v[i])

dp_pre[j]存储上一次得到的值,现在只需要2*n的空间就能得到结果。继续观察可以发现,其实只用一个一维dp数组就行,不需要额外的辅助数组。让j从n到1遍历,此时每次更新的dp[j]时,max函数中dp[j]和 dp[j-w[i]]都是上次保存的值。

状态转移方程变为:
for j in [n...1]:
dp[j] = max(dp[j], dp[j-w[i]]+v[i])

''' 定义一维数组时,a=[0]*n
    在定义二维数组的时,a = [[0]*(n) for _ in range(m)] (m行n列)  '''
# 背包价格容量n元  物品数量m件
n, m = map(int, input().split())  # 第一个参数接受一个函数名,后面的参数接受一个或多个可迭代的序列,返回的是一个集合。
n = n // 10

# 物品价格,主件,附件1,附件2
w = [[0] * 3 for _ in range(m + 1)]
# 物品价值,主件,附件1,附件2
val = [[0] * 3 for _ in range(m + 1)]

for i in range(1, m + 1):
    v, p, q = map(int, input().split())  # v-物品价格 p-物品重要度 q-主件/附件
    v = v // 10
    if q == 0:  # 为主件
        w[i][0] = v
        val[i][0] = p * v
    elif w[q][1] == 0:  # 附件1
        w[q][1] = v
        val[q][1] = p * v
    else:  # 附件2
        w[q][2] = v
        val[q][2] = p * v

dp = [[0] * (n + 1) for _ in range(m + 1)]
for i in range(1, m + 1):  # 第i件
    for j in range(1, n + 1):  # j元

        if j - w[i][0] >= 0:  # 主件
            dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - w[i][0]] + val[i][0])
        if j - w[i][0] - w[i][1] >= 0:  # 主件+附件1
            dp[i][j] = max(dp[i - 1][j],dp[i][j], dp[i - 1][j - w[i][0] - w[i][1]] + val[i][0] + val[i][1])
        if j - w[i][0] - w[i][2] >= 0:  # 主件+附件2
            dp[i][j] = max(dp[i - 1][j], dp[i][j],dp[i - 1][j - w[i][0] - w[i][2]] + val[i][0] + val[i][2])
        if j - w[i][0] - w[i][1] - w[i][2] >= 0:  # 主件+附件1+附件2
            dp[i][j] = max(dp[i - 1][j],dp[i][j], dp[i - 1][j - w[i][0] - w[i][1] - w[i][2]] + val[i][0] + val[i][1] + val[i][2])
        else:
            dp[i][j] = dp[i - 1][j]

print(dp[m][n] * 10)

  • HJ17 坐标移动

 

while True:
    try:
        input_str = input().split(';')      #//去掉空格,并以';'为分隔符
        # dir_xy = {'A': 1, 'D': 2, 'W': 3, 'S': 4}   #字典
        x, y = 0, 0
        for i in input_str:
            try:
                number = int(i[1:]) #直接int化位移数,由于使用了try,所有非法的情况都会被跳过
                if not 0 <= number <= 99:       #//判断是否在两位数以内
                    continue        # 如果在循环中达到到某些条件则跳过当次循环而不是终止整个循环的时候可以利用 continue 来实现。
                flag = i[0]
                if flag == 'A':
                    x = x - number
                if flag == 'D':
                    x = x + number
                if flag == 'S':
                    y = y - number
                if flag == 'W':
                    y = y + number
            except:
                continue        #try:尝试执行的代码  except:出现错误的处理
        print("%s,%s" % (x, y))
    except :
         break      #continue 跳出本次循环  break跳出整个循环
  • HJ18 识别有效的IP地址和掩码并进行分类统计

 

深入理解Lambda函数及其用法

map函数与lambda函数结合使用

 在Python中try,except,finally的用法_python try except finally_Python 学习者的博客-CSDN博客

  

 

import re  # Python中re模块主要功能是通过正则表达式是用来匹配处理字符串的


def is_else_ip(ip):  # 判断【0.*.*.*】和【127.*.*.*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时请忽略
    nums = ip.split(".")
    if int(nums[0]) == 0 or int(nums[0]) == 127:
        return True
    return False


def is_legal_ip(ip):  # 判断是否合法
    if not ip:
        return False
    pattern = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")  # 正则表达式
    '''compile() 编译正则表达式模式,返回pattern对象。
        \d ——数字
        ^  ——匹配字符串的开始
        $  ——匹配字符串的结束
        {1,3}——匹配至少1次,至多3次
        match() 用正则表达式匹配字符串,成功返回匹配对象,否则返回None'''
    match = pattern.match(ip)
    if not match:
        return False

    nums = ip.split(".")
    for num in nums:
        if int(num) < 0 or int(num) > 255:
            return False
    return True


def catagory(ip):  # 判断类型
    if not ip:
        return False

    nums = ip.split(".")
    # A  1.0.0.0~126.255.255.255
    if 126 >= int(nums[0]) >= 1:
        return "A"
    # B  128.0.0.0~191.255.255.255
    if 191 >= int(nums[0]) >= 128:
        return "B"
    # C  192.0.0.0~223.255.255.255
    if 223 >= int(nums[0]) >= 192:
        return "C"
    # D  224.0.0.0~239.255.255.255
    if 239 >= int(nums[0]) >= 224:
        return "D"
    # E  240.0.0.0~255.255.255.255
    if 255 >= int(nums[0]) >= 240:
        return "E"

    return False


def is_private(ip):  # 私网
    if not ip:
        return False

    nums = ip.split(".")
    #   10.0.0.0~10.255.255.255
    if int(nums[0]) == 10:
        return True
    #   172.16.0.0~172.31.255.255
    if int(nums[0]) == 176:
        if 31 >= int(nums[0]) >= 16:
            return True
    #   192.168.0.0~192.168.255.255
    if int(nums[0]) == 192 and int(nums[1]) == 168:
        return True

    return False


def is_legal_mask_code(mask):  # 私网
    if not mask:
        return False

    binary_mask = "".join(map(lambda x: bin(int(x))[2:].zfill(8), mask.split(".")))
    '''zfill(8) 填充数字字符串左侧的零,以填充给定宽度8的字段。字符串永远不会被截断。
       bin(int(x))[2:] 2进制不要0b 
       lambda本质上是个函数功能,是个匿名的函数'''

    index_first_zero = binary_mask.find("0")
    index_last_zero = binary_mask.rfind("1")
    if index_last_zero > index_first_zero:
        return False
    return True


A, B, C, D, E, Err, P = 0, 0, 0, 0, 0, 0, 0
try:
    while True:
        ip, mask = input().split("~")
        if is_else_ip(ip):
            continue

        if not is_legal_ip(ip) or not is_legal_mask_code(mask):
            Err += 1
        else:
            if is_private(ip):
                P += 1
            cat = catagory(ip)
            if cat == "A":
                A += 1
            if cat == "B":
                B += 1
            if cat == "C":
                C += 1
            if cat == "D":
                D += 1
            if cat == "E":
                E += 1
except:
    pass
finally:
    print(A, B, C, D, E, Err, P)
  • HJ19 简单错误记录 

 Python的字典操作_python字典的基本操作_斩心之鬼的博客-CSDN博客

# 全局变量
result = dict()  # 字典
records = []

while True:
    try:
        list1 = input().split()  # 带路径文件名  行号
        name = list1[0].split('\\')[-1][-16:]
        '''split('\\')-反斜杠分割 E:\\je\\rzuwnjvnuz
            [-1]-rzuwnjvnuz
            [-16:]-保留最后16位 -16到最后
        '''
        record = name + ' ' + list1[1]  # 文件名 + 空格 + 行数  'rzuwnjvnuz 633'

        result[record] = result.get(record, 0) + 1
        '''
        result[record] - 访问键值为 record 的Value
        result.get(record, 0) - 访问键为 record 的值,键不存在,返回default值0
        '''
        if record not in records:
            records.append(record)  # 将对象追加到列表的末尾
    except:
        for i in records[-8:]:          #记录最多8条错误记录,循环记录,最后只用输出最后出现的八条错误记录
            print(i + " " + str(result[i]))
        break
  •  HJ20 密码验证合格程序

 

def check(s):
    if len(s) <= 8:         # 判断密码的长度
            return  False
    a, b, c, d = 0, 0, 0, 0
    for i in s:
        if i.islower():  # 小写字母
            a = 1
        elif i.isupper():  # 大写字母
            b = 1
        elif ord('0') <= ord(i) <= ord('9'):  # 数字
            # elif c.isdigit():
            c = 1
        else:  # 其他字符
            d = 1
    if a+b+c+d<3:
        return False

    for i in range(len(s) - 2):  # 循环遍历找到子字符串的起点
        if s[i:i + 3] in s[i + 3:]:  # 在剩下的字符串中顺序查找匹配当前字符串
            return False

    # dc = {}
    # for i in range(len(pw) - 2):  # 遍历所有的子字符串起点
    #     if pw[i:i + 3] in dc:  # 在字典中搜索
    #         return False
    #     else:  # 如果未曾经出现过则加入字典中,等待之后的判定
    #         dc[pw[i:i + 3]] = 1

    return True

while True:
    try:
        password=input()
        if check(password):
            print('OK')
        else:
            print('NG')
    except:
        break

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值