华为机试108题 11-20

11. 数字颠倒 12. 字符串反转

  • 输入一个整数,将这个整数以字符串的形式逆序输出
  • 程序不考虑负数的情况,若数字含有0,则逆序形式也含有0,如输入为100,则输出为001
  • 输入:输入一个int整数
  • 输出:将这个整数以字符串的形式逆序输出

示例:

输入
1516000
输出
0006151

思路:

字符串反转

代码实现:

str_num = str(input())
print(str_num[::-1])

13. 句子逆序

  • 将一个英文语句以单词为单位逆序排放。例如“I am a boy”,逆序排放后为“boy a am I”
    所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含其他字符
  • 输入:将一个英文语句以单词为单位逆序排放。
  • 输出:得到逆序的句子

示例:

输入
I am a boy
输出
boy a am I

思路:

将每个单词放入列表,列表逆序,再使用join()函数转为字符串

代码实现:

sentence_list = input().split(' ')
reverse_list = sentence_list[::-1]
print(' '.join(reverse_list))

14. 字串的连接最长路径查找

  • 给定n个字符串,请对n个字符串按照字典序排列。
  • 输入:输入第一行为一个正整数n(1≤n≤1000),下面n行为n个字符串(字符串长度≤100),字符串中只含有大小写字母。
  • 输出:数据输出n行,输出结果为按照字典序排列的字符串。

示例:

输入
9
cap
to
cat
card
two
too
up
boat
boot
输出
boat
boot
cap
card
cat
to
too
two
up

思路:

使用sorted()函数排序

代码实现:

import sys
while True:
    try:
        n = int(sys.stdin.readline())
        lst = []
        for i in range(n):
            lst.append(sys.stdin.readline().strip())
        sort_list = sorted(lst)
        for i in sort_list:
            print(i)
    except:
        break

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

  • 输入一个int型的正整数,计算出该int型数据在内存中存储时1的个数。
  • 输入:输入一个整数(int类型)
  • 输出:这个数转换成2进制后,输出1的个数

示例:

输入
5
输出
2

思路:

十进制转二进制:
用十进制整数除以2,余数作为二进制字符首位,将商再除以2,余数作为二进制字符第二位,重复过程,直到商为0

代码实现:

num = int(input())
i_str = ''
while num != 0:
    i_str += str(num % 2)
    num //= 2

print(i_str.count('1'))

16. 购物单

  • 王强今天很开心,公司发给N元的年终奖。王强决定把年终奖用于购物,他把想买的物品分为两类:主件与附件,附件是从属于某个主件的,下表就是一些主件与附件的例子:
    在这里插入图片描述
    如果要买归类为附件的物品,必须先买该附件所属的主件。每个主件可以有 0 个、 1 个或 2 个附件。附件不再有从属于自己的附件。王强想买的东西很多,为了不超出预算,他把每件物品规定了一个重要度,分为 5 等:用整数 1 ~ 5 表示,第 5 等最重要。他还从因特网上查到了每件物品的价格(都是 10 元的整数倍)。他希望在不超过 N 元(可以等于 N 元)的前提下,使每件物品的价格与重要度的乘积的总和最大。
    设第 j 件物品的价格为 v[j] ,重要度为 w[j] ,共选中了 k 件物品,编号依次为 j 1 , j 2 ,……, j k ,则所求的总和为:
    v[j 1 ]*w[j 1 ]+v[j 2 ]*w[j 2 ]+ … +v[j k ]*w[j k ] 。(其中 * 为乘号)
    请你帮助王强设计一个满足要求的购物单。

17. 坐标移动

  • 开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。

输入:
合法坐标为A(或者D或者W或者S) + 数字(两位以内)
坐标之间以;分隔。
非法坐标点需要进行丢弃。如AA10; A1A; % ; YAD; 等。
下面是一个简单的例子 如:
A10;S20;W10;D30;X;A1A;B10A11;;A10;
处理过程:
起点(0,0)

  • A10 = (-10,0)
  • S20 = (-10,-20)
  • W10 = (-10,-10)
  • D30 = (20,-10)
  • x = 无效
  • A1A = 无效
  • B10A11 = 无效
  • 一个空 不影响
  • A10 = (10,-10)
    结果 (10, -10)
  • 输入:一行字符串
  • 输出:最终坐标,以,分隔

示例:

输入
A10;S20;W10;D30;X;A1A;B10A11;;A10;
输出
10,-10

思路:

将字符串按照分号 “ ; ” 分割,遍历每一个片段,使用re匹配

代码实现:

import sys
import re

while True:
    try:
        origin = [0, 0]
        move_list = input().strip().split(';')
        for i in move_list:
            ret = re.match(r'^([WASD])([0-9]?[0-9])$', i)
            if ret:
                if ret.group(1) == 'W':
                    origin[1] += int(ret.group(2))
                elif ret.group(1) == 'S':
                    origin[1] -= int(ret.group(2))
                elif ret.group(1) == 'A':
                    origin[0] -= int(ret.group(2))
                elif ret.group(1) == 'D':
                    origin[0] += int(ret.group(2))
            else:
                continue
        print(str(origin[0])+','+str(origin[1]))
    except:
        break

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

  • 请解析IP地址和对应的掩码,进行分类识别。要求按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。
    所有的IP地址划分为 A,B,C,D,E五类
    A类地址1.0.0.0~126.255.255.255;
    B类地址128.0.0.0~191.255.255.255;
    C类地址192.0.0.0~223.255.255.255;
    D类地址224.0.0.0~239.255.255.255;
    E类地址240.0.0.0~255.255.255.255
    私网IP范围是:
    10.0.0.0~10.255.255.255
    172.16.0.0~172.31.255.255
    192.168.0.0~192.168.255.255
    子网掩码中每个数字都为8位二进制,总体要求前面是连续的1,然后全是0。(例如:255.255.255.32就是一个非法的掩码)
    注意二进制下全是1或者全是0均为非法

注意:

  1. 类似于【0...*】的IP地址不属于上述输入的任意一类,也不属于不合法ip地址,计数时可以忽略
  2. 私有IP地址和A,B,C,D,E类地址是不冲突的
  • 输入:多行字符串。每行一个IP地址和掩码,用~隔开。
  • 输出:统计A、B、C、D、E、错误IP地址或错误掩码、私有IP的个数,之间以空格隔开。

示例:

输入
10.70.44.68~255.254.255.0
1.0.0.1~255.0.0.0
192.168.0.2~255.255.255.0
19..0.~255.255.255.0
输出
1 0 1 0 0 2 1

思路:

先判断子网掩码,若不通过,直接计错误并进行下一循环。
子网掩码只能从 [‘255’, ‘254’, ‘252’, ‘248’, ‘240’, ‘224’, ‘192’, ‘128’, ‘0’] 中取。

代码实现:

import sys

A, B, C, D, E, err, pri = 0, 0, 0, 0, 0, 0, 0
while True:
    try:
        ip_subnet = sys.stdin.readline().strip().split('~')
        ip = ip_subnet[0]
        subnet = ip_subnet[1]

        # 判断子网掩码
        subnet_mask = True
        subnet_list = subnet.split('.')
        # 将子网掩码变为二进制,拼成字符串
        subnet_first = bin(int(subnet_list[0]))[2:]
        subnet_second = bin(int(subnet_list[1]))[2:]
        subnet_third = bin(int(subnet_list[2]))[2:]
        subnet_forth = bin(int(subnet_list[3]))[2:]
        subnet_str = subnet_first + subnet_second + subnet_third + subnet_forth
        # 判断子网掩码是否都为1或都为零
        if subnet_str.count('1') == 0 or subnet_str.count('0') == 0:
            subnet_mask = False
            err += 1
            continue
        # 判断是否1之后都是0
        zero_index = subnet_str.index('0')
        for i in range(zero_index, len(subnet_str)):
            if subnet_str[i] == '1':
                subnet_mask = False
                break
        # 判断子网掩码是否在['255', '254', '252', '248', '240', '224', '192', '128', '0']内
        subnet_str_lst = [subnet_first, subnet_second, subnet_third, subnet_forth]
        for i in subnet_str_lst:
            if i not in [bin(255)[2:], bin(254)[2:], bin(252)[2:], bin(248)[2:], bin(240)[2:], bin(224)[2:], bin(192)[2:], bin(128)[2:], '0']:
                subnet_mask = False
                break
        if not subnet_mask:
            err += 1
            continue

        # 判断ip类型
        ipA = ipB = ipC = ipD = ipE = error = private = False
        ip_list = ip.split('.')
        ip_first = int(ip_list[0])
        ip_second = int(ip_list[1]) if len(ip_list[1]) else ''
        ip_third = int(ip_list[2]) if len(ip_list[2]) else ''
        ip_forth = int(ip_list[3]) if len(ip_list[3]) else ''

        if ip_first != '' and ip_second != '' and ip_third != '' and ip_forth != '':
            if 1 <= ip_first <= 126 and 0 <= ip_second <= 255 and 0 <= ip_third <= 255 and 0 <= ip_forth <= 255:
                A += 1
            elif 128 <= ip_first <= 191 and 0 <= ip_second <= 255 and 0 <= ip_third <= 255 and 0 <= ip_forth <= 255:
                B += 1
            elif 192 <= ip_first <= 223 and 0 <= ip_second <= 255 and 0 <= ip_third <= 255 and 0 <= ip_forth <= 255:
                C += 1
            elif 224 <= ip_first <= 239 and 0 <= ip_second <= 255 and 0 <= ip_third <= 255 and 0 <= ip_forth <= 255:
                D += 1
            elif 240 <= ip_first <= 255 and 0 <= ip_second <= 255 and 0 <= ip_third <= 255 and 0 <= ip_forth <= 255:
                E += 1
            # 判断私有ip
            if ip_first == 10 and 0 <= ip_second <= 255 and 0 <= ip_third <= 255 and 0 <= ip_forth <= 255 \
                    or ip_first == 172 and 16 <= ip_second <= 31 and 0 <= ip_third <= 255 and 0 <= ip_forth <= 255 \
                    or ip_first == 192 and ip_second == 168 and 0 <= ip_third <= 255 and 0 <= ip_forth <= 255:
                pri += 1
        else:
            err += 1

    except:
        break

print("%s %s %s %s %s %s %s" % (A, B, C, D, E, err, pri))

19. 简单错误记录

  • 开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。
    处理:
    1、 记录最多8条错误记录,循环记录(或者说最后只输出最后出现的八条错误记录),对相同的错误记录(净文件名称和行号完全匹配)只记录一条,错误计数增加;
    2、 超过16个字符的文件名称,只记录文件的最后有效16个字符;
    3、 输入的文件可能带路径,记录文件名称不能带路径。
  • 输入:一行或多行字符串。每行包括带路径文件名称,行号,以空格隔开。
  • 输出:将所有的记录统计并将结果输出,格式:文件名 代码行数 数目,一个空格隔开。

示例:

输入:
G:\rp\onajqj\maahmq 631 
E:\njfgjkcrh 641 
C:\co\zk\ao\bxgxjfgrwckfxekeqro 629 
D:\mf\si\jmfdahkeffyjjsf 646 
……
G:\zsw\uewu\arefkiz 634 
E:\ja\zg\njfgjkcrh 644 
D:\gfute\ju\wuy\szxcdhlaytgj 636 
C:\mpgcx\kcgi\arefkiz 645 
C:\zayn\jmfdahkeffyjjsf 648 
F:\kkplu\avvw\hbzmwj\jmfdahkeffyjjsf 648 
E:\maahmq 631 
E:\hs\xnto\jmfdahkeffyjjsf 645 
G:\cqekvaxypemktyurn 633 
D:\maahmq 646 
E:\jmfdahkeffyjjsf 636 
G:\hbvm\szxcdhlaytgj 642
输出
szxcdhlaytgj 636 1
arefkiz 645 1
jmfdahkeffyjjsf 648 2
jmfdahkeffyjjsf 645 1
qekvaxypemktyurn 633 1
maahmq 646 1
jmfdahkeffyjjsf 636 1
szxcdhlaytgj 642 1

注意maahmq 631 已经在第一个出现过,因此后面再出现时,将其加在第一个上,即不在最后8个结果中出现

思路:

因为此处有三个变量:文件名、行号、出现次数
因此我们可以将‘文件名 行号’作为字典的键,出现次数作为值,进行累加

代码实现:

import sys

hash_map = {}
error_log = []
while True:
    try:
        s_list = sys.stdin.readline().strip().split()
        file_name = s_list[0].split('\\')[-1]
        max_filename = file_name[-16:]
        error_line = s_list[1]

        log = max_filename + ' ' + error_line
        if log not in hash_map:
            hash_map[log] = 1
            error_log.append(log)
        else:
            hash_map[log] += 1

    except:
        break

for i in error_log[-8:]:
    print(i + ' ' + str(hash_map[i]))

20. 密码验证合格程序

  • 密码要求:
    1.长度超过8位
    2.包括大小写字母.数字.其它符号,以上四种至少三种
    3.不能有长度大于2,且相同的子串出现
    说明:长度超过2的子串
  • 输入:一组或多组长度超过2的子符串。每组占一行
  • 输出:如果符合要求输出:OK,否则输出NG

示例:

输入
021Abc9000
021Abc9Abc1
021ABC9000
021$bc9000
输出
OK
NG
NG
OK

思路1

1, 2要求不难实现,对于3,可使用列表切片三个三个向后切,每切一次,将其放入哈希表,若在哈希表中遇到同样切片,输出NG

代码实现1

import sys

while True:
    try:
        s = input().strip()
        # 长度超过8位
        if len(s) <= 8:
            print('NG')
            continue
        # 至少三种字符
        num = upper = lower = other = 0
        for i in s:
            if '0' <= i <= '9':
                num = 1
            elif 'A' <= i <= 'Z':
                upper = 1
            elif 'a' <= i <= 'z':
                lower = 1
            else:
                other = 1
        if num + upper + lower + other < 3:
            print('NG')
            continue
        
        # 相同长度超2的子串
        hash_map = {}
        sub_str = True
        for i in range(3, len(s)):
            if s[i-3:i] not in hash_map:
                hash_map[s[i-3:i]] = 1
            else:
                print('NG')
                sub_str = False
                break
        if not sub_str:
            continue
        
        # 都通过
        print('OK')
        
    except:
        break

思路2:正则表达式

反向引用:

  • 例:
    当一条字符串中含有2(组/个)连续的字符时,该字符串可以称之为“连续的字符串”。
    比如:2034384538452可以成为“连续的字符串”,因为其含有2次连续的3845。
    请找出能够判断“连续的字符串”的方法,输入可以用字符串或数组,输入不能为空,并且字符串长度必须大于等于1。
import re
re.compile(r'(.+)\1').search

表达式在匹配时,表达式引擎会将小括号 “( )” 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以单独获取。
“\1” 引用第1对括号内匹配到的字符串,”\2” 引用第2对括号内匹配到的字符串……以此类推。
如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 “(“ 在前,那这一对为先。

回归题目:
a中[ (.{3,}).* ]是指[(3-n个任意字符)跟随(任意个任意字符)]这一[组合],\1表示向前引用,所以正则表达式的形式为[组合]…[组合],在s中寻找这一形式是否存在,返回值赋予给a

代码实现2:

import re

while True:
    try:
        s = input()
        a = re.findall(r'(.{3,}).*\1', s)  # 只匹配到一个不出现结果
        b1 = re.findall(r'\d', s)
        b2 = re.findall(r'[A-Z]', s)
        b3 = re.findall(r'[a-z]', s)
        b4 = re.findall(r'[^0-9A-Za-z]', s)
		
		# 如果re.findall()未匹配到,则返回空列表,
		# b1-b4至多有一个空列表,保证b1-b4至少三个有匹配结果
		# 为保证长度大于2,且相同的子串不出现,要求a中不能出现结果
        ret = 'OK' if ([b1, b2, b3, b4].count([]) <= 1 and a == [] and len(s) > 8) else 'NG'
        print(ret)
    except:
        pass
发布了51 篇原创文章 · 获赞 4 · 访问量 3512

猜你喜欢

转载自blog.csdn.net/yhhuang17/article/details/105051020
今日推荐