牛客华为机试题刷题笔记总结[103题更新完毕才收尾,建议关注收藏]

面试题链接:https://www.nowcoder.com/exam/oj/ta?difficulty=1&page=1&pageSize=50&search=&tpId=37&type=37

下方的补充包含了所有题中的精华,可时常拿来复习

  • 补充合集
    • 补充合集在此
      • 正则表达式
      • 最小公约数和最小公倍数
      • 0-1背包问题
      • 最长递增子序列
      • levenshtein距离
      • 最长公共子串
      • 双层切片
      • 递归解决暴力枚举的计算问题
      • 利用list制作矩阵
      • 乘法计算量计算
      • 排列组合
      • 补充两道考过的华为机试题
      • 动态规划专栏
      • 补充贪心思想+最大cover思想
      • gcd (greatest common divisor)

补充合集

补充合集在此

a, b = b, a#交换
子串:必须连续,子序列:可以不连续
python 不支持do while
round( x [, n]  )方法返回浮点数x的四舍五入值。n -- 数值表达式,表示从小数点位数。
a//b,应该是对除以b的结果向负无穷方向取整后的数
import math 
math.ceil(n)
math.floor(n)
try:
    b, c = a.split(".", 2) #str.split(str="", num=string.count(str)). num为分割次数,1次分成两半,返回list 
    #如果第二个参数 num 有指定值,则分割为 num+1 个子字符串。
except ValueError:  # 如果不含小数点
    print(a)
else:  # 如果含小数点
    if int(c[0]) >= 5:
        print(int(b) + 1)
    else:
        print(int(b))

关于数组的初始化:
array = [item for v in range(10)] 
array = [item]*10
初始化创建n行m列数组  
n = 3
m = 3
matrix = ['init']*n
for i in range(len(matrix)): 
  matrix[i] = ['PY']*m #把init的值覆盖了
print(matrix)

关于反转:
print(input()[::-1])#啥反转都可以用这个
num_list[-k] 取倒数的第k个
def reverseString_1(self, s):
        """
        思路:借助一个中间变量temp,然后从s的尾部提取,把元素追加到temp中
        """
        temp = []
        for i in range(len(s)):
            temp.append(s[len(s)-1-i])
        return temp
def reverseString(self, s):
        """
        :type s: List[str]
        :rtype: None Do not return anything, modify s in-place instead.
        """
        i = 0  # 第一个指针,从首部遍历
        j = len(s) - 1  # 第二个指针,从尾部遍历

        while j > i: # 如果j>i就一直循环,直到2个指针相遇
            s[i], s[j] = s[j], s[i]  # 交换2个位置的元素
            i += 1
            j -= 1
        return s
def reverseString(self, s):
        """
        思路:切片【前闭后开!!!range也是】
        s[::-1]表示反转s中的元素
        s[:]表示数组中所有子模块
        s[:]=s[::-1]表示将原数组反转后赋值给s中每一个对应的位置
        s=s[::-1]表示将s反转后赋值给新的对象s,与题意原地修改不符

        :param s:
        :return:
        """
        s[:] = s[::-1]
        return s
#string->array/list:for循环+[].append

def reverseString_6(self, s):#只对list有效
        """
        :param s:
        :return:
        """
        s.reverse()
        return s

关于分割成单个字符:
for item in a:
	print(item)

常见去重方法:
用集合的特性set(),去重后顺序会改变
a = ['1', '2', 'x', '5', 'x']
print(set(a))
这里补充set()基本操作:set() 函数创建一个无序不重复元素集,可进行关系测试,删除重复数据,还可以计算交集、差集、并集等。
交集 & : x&y,返回一个新的集合,包括同时在集合 x 和y中的共同元素。
并集 | : x|y,返回一个新的集合,包括集合 x 和 y 中所有元素。
差集 - : x-y,返回一个新的集合,包括在集合 x 中但不在集合 y 中的元素。
补集 ^ : x^y,返回一个新的集合,包括集合 x 和 y 的非共同元素。

a = ['1', '2', 'x', '5', 'x']
list = []
for i in a:#循环查找
    if i not in list:
        list.append(i)
print(list)       ----['1', '2', 'x', '5']

list->str类型:
"".join(nums)

如果列表 [ ] 里面含有的元素是整形int ,需要将整形int 转换成str类型。
strNums=[str(x) for x in nums]
print("".join(strNums))

str->listlist(str)即可

如何不带回车输出?print('你需要输出的内容',end='')

多输入制作成list:
a = int(input())            #输入要排列元素个数
b = input().split()         #将输入的元素存放到列表中
b.sort(reverse=True)        #用sort()函数将列表中的元素从大到小排序
for i in range(0,a):
    print(b[i],end=' ')     #输出的数之间用空格隔开
若要对负数也进行排序,则需对输入的每个数进行化整型

合并列表:直接使用"+"号合并列表
注意a.append(b)将b看成list一个元素和a合并成一个新的list[1, 2, 3, ['www', 'jb51.net']]它直接把bList当成了一个元素整个放入了aList

解决ValueError: invalid literal for int() with base 10: str->int' '问题,解决多输入以空格分割的问题
str = input()
li = str.split(' ')#以空格为条件,将字符串拆分成列表

将列表每个数都强制转换为int:
num_list_new = list(map(int, num_list))
num_list_new = [int(i) for i in num_list]

int ->str:str()

ascii码以及大小写字母关系+数字起始:
485709
659026个大写英文字母,A~Z
97122号为26个小写英文字母,a~z
大写+32=小写
#ord(‘字符’)可以返回该字符的ASCII码
print(ord('a'))
根据ascii码输出字母 chr(ascii)

a[i:j+1] in b表示查找此串是否为b的子串
str的截取:
当以字符串的右端(字符串的末尾)为起点时,索引是从 -1 开始计数的;字符串的倒数第一个字符的索引为 -1,倒数第二个字符的索引为 -2,倒数第三个字符的索引为 -3 …
获取多个字符
str[start: end: step]
str: 字符串名称
start: 要获取的第一个字符串所在的索引(包含该字符)。如果不指定,则默认为0,从字符串开头开始
end: 要获取的最后一个字符所在的索引(不包含此字符)。不指定,则默认为字符长度,即最后一个
step:获取字符的步长,默认为1,当省略该值时,最后一个参数也可以省略 每step个取1return:在定义函数时从函数中返回一个函数的返回值,终止函数的执行。
os._exit(),sys.exit(),exit(),quit()都能够退出当前执行脚本,差别在于os._exit()直接退出,sys.exit(),exit(),quit()始终会抛出一个SystemExit异常。如果不捕获异常,看起来的效果和 os._exit() 一样,不会有任何意外的信息,但也可以捕获这些异常来做一些清理的工作try:
        for i in range(10):
            time.sleep(0.5)
            print(i)
        print 'eeeee'
    except:
        print(sys.exc_info()[0])
        print(sys.exc_info())
        print 'clean'

进制转换:
int()类可将数字或字符串转换为整型,以及把各进制转为十进制,调用方法为:
int(x, base=10)
>>> int('55')    #字符串转换为十进制整型数
55
>>> int(0b11)    #二进制转换为十进制
3
>>> int(0o11)    #八进制转换为十进制
9
>>> int(0x11)    #十六进制转换为十进制
17

int(x, 0)适用于带0x标示的各种进制数转十进制,
若不带0x的各种进制数要在后面的base中写明这是几进制,如x = int("deadbeef", 16)表明是16进制转十进制

使用bin(x) ,oct(x)hex(x) 转换:
传入的参数可以是2816进制的,输出是字符串形式

使用format() 转换 :format是字符串内嵌的一个方法,用于格式化字符串。以大括号{}来标明被替换的字符串。
url:https://blog.csdn.net/qq_42855293/article/details/118480087
s = "{:b}".format(8) #转换为二进制
print(s) # 1000
s = "{:o}".format(8) #八进制
print(s) # 10
s = "{:X}".format(12) #十六进制
print(s) # C

while():

string合集:来自另一位博主的版权声明:本文为CSDN博主「崔沐橙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/windowsworld/article/details/93377993

print(s * 5)
#连接
print(-.join(date1))
print(..join(s2))

is___,判断输出都为TrueFalse的函数大合集:
i.istitle()判断i是否为题目,即首字母大写
i.isupper()判断是否为全大写
i.islower() 判断是否为全小写
i.upper() 转换i为大写
i.lower()转换i为小写
i.isalpha()检测字符串是否只由字母组成
i.isdigit()检测字符串是否只由数字组成
isnumeric() 如果字符串中只包含数字字符,则返回 True,否则返回 False。
i.isspace()检测字符串是否只由空格组成
i.isalnum()检测字符串是否由字母和数字组成。
s.swapcase() 方法用于对字符串的大小写字母进行转换,即将大写字母转换为小写字母,小写字母会转换为大写字母。

#判断文件类型是否以.log结尾
filename = ‘hello.log’
if filename.endswith(.log’):
print(filename)
else:
print(‘error’)

strip()删除字符串首尾,只要首尾两端的字符在 chars 之内,就会被删除,直到遇到第一个不在 chars 内的字符。
print(a.strip())##去除两边的空格
print(a.lstrip())##去除左边的空格
print(a.rstrip())##去除右边的空格
print(b.lstrip(‘h’))##去除左边的h

字符串的搜索和替换
s = ‘hello world hello’
#find找到子串并返回最小的索引 
#注意list的查找索引是list.index(x) x为值,返回其下标,若不存在抛出异常
print(s.find(‘hello’))
print(s.find(‘world’))
#find找到子串并返回最大的索引
print(s.rfind(‘hello’))
print(s.lfind(‘world’))
#字符串替换
print(s.replace(’ ‘,’ westos’)) 把‘ ’替换为westos
#字符串统计
print(s.count(‘l’))
print(s.count(“l”))
#开头结尾匹配
endswith(suffix, beg=0, end=len(string)) 检查字符串是否以指定子字符串 suffix 结束,如果是,返回 True,否则返回 False。如果 beg 和 end 指定值,则在指定范围内检查。
startswith(substr, beg=0,end=len(string)) 检查字符串是否以指定子字符串 substr 开头,如果是,返回 True,否则返回 False。如果 beg 和 end 指定值,则在指定范围内检查。
#对齐+填充字符
ljust(width[, fillchar])返回一个原字符串左对齐,并使用fillchar(默认空格)填充至长度width的新字符串。
rjust(width[, fillchar])返回一个原字符串右对齐,并使用fillchar(默认空格)填充至长度width的新字符串。


得到某串中重复子串:利用切片+count函数

list操作:
#排序
list.sort( key=None, reverse=False)
Python中对集合排序可以将集合转换为列表,然后通过list.sort()函数将列表排序,排序结果就是集合的排序结果。
集合-->列表-->list.sort() 
#例
# 获取列表的第二个元素
def takeSecond(elem):
    return elem[1]
random = [(2, 2), (3, 4), (4, 1), (1, 3)]
# 指定第二个元素排序
random.sort(key=takeSecond)

#删除
del e[3]
a.remove(3)

#输出元素
a.index(3)


次方运算:**
math.sqrt(n)

python 字典操作 dictionary:
d = {key1 : value1, key2 : value2 }
del tinydict['Name']  # 删除键是'Name'的条目
tinydict.clear()      # 清空字典所有条目
del tinydict          # 删除字典
dict(zip(list1,list2))打包两个list放入dic,list1中元素作key,list2中作value
cmp(dict1, dict2)比较两个字典元素:如果两个字典的元素相同返回0,如果字典dict1大于字典dict2返回1,如果字典dict1小于字典dict2返回-1len(dict)计算字典元素个数,即键的总数。
str(dict)输出字典可打印的字符串表示。
dict.has_key(key)如果键在字典dict里返回true,否则返回false !!!被移除了,现在用in代替
dict.keys()以列表返回一个字典所有的键
dict.values()以列表返回字典中的所有值
dict.update(dict2)把字典dict2的键/值对更新到dict里,添加元素或如果后面的键有重复的会覆盖前面的
dict.pop(key[,default])
删除字典给定键 key 所对应的值,返回值为被删除的值。key值必须给出。 否则,返回default值。
popitem()返回并删除字典中的最后一对键和值。
key,value/item in chengji.items()返回键值对
keys()/values()
遍历字典:
chengji = {'语文':'88','数学':'96','英语':'86'}
for item in chengji.items():
    print(item)
('语文', '88')
('数学', '96')
('英语', '86')

chengji = {'语文':'88','数学':'96','英语':'86'}
for key,value in chengji.items():
    print(key,"的成绩是",value)

对字典分别按键(key)和值(value)进行排序————————————————版权声明:本文为CSDN博主「冠亦Python」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/SX77661/article/details/122144874

list = sorted(iterable, key=None, reverse=False)  
其中,iterable 表示指定的序列,key 参数可以自定义排序规则,可以接受一个函数,该函数的功能是指定 sorted() 函数按照什么标准进行排序;
例如:chars=['http://c.biancheng.net',\
       'http://c.biancheng.net/python/',\
       'http://c.biancheng.net/shell/',\
       'http://c.biancheng.net/java/',\
       'http://c.biancheng.net/golang/']
#自定义按照字符串长度排序
print(sorted(chars,key=lambda x:len(x)))
reverse 参数指定以升序(False,默认)还是降序(True)进行排序。
sorted() 函数会返回一个排好序的列表。


#对字典按键(key)进行排序(默认由小到大)
test_data_0=sorted(dict_data.keys(),reverse=False) 
#输出结果
print(test_data_0) #[3, 6, 7, 8, 10] 

#连带一起排序
test_data_1=sorted(dict_data.items(),key=lambda x:x[0]) #lambda x:x[0]是一个整体
#输出结果
print(test_data_1) 
#[(3, 11), (6, 9), (7, 6), (8, 2), (10, 5)]

#先按照成绩降序排序,相同成绩的按照名字升序排序:
d1 = [{'name':'alice', 'score':38}, {'name':'bob', 'score':18}, {'name':'darl', 'score':28}, {'name':'christ', 'score':28}]
l = sorted(d1, key=lambda x:(-x['score'], x['name']))#一定要用括号括起来


lamda是什么?匿名(函数)或者lambda函数用于指定对列表中每一个元素的共同操作 或者用于指定对列表中所有元素进行排序的准则

c语言里面if(!x)中的!换成not,但是不等于依然是!=

栈的实现:.append:末尾添加 与.pop方法:移除末尾
pop方法也用于set/dic/list

质因子结论:输在了数学结论上,质因子(或质因数)在数论里是指能整除给定正整数的质数。根据算术基本定理,不考虑排列顺序的情况下,每个正整数都能够以唯一的方式表示成它的质因数的乘积。故应该得到如果它能除一个质数,则后续因子均为质因数,且只有这一种结果。而数要么是质数,要么不是质数,如果不是则一定可以除2/3,因为能除2的倍数就能除2,能除3的倍数就能除3,(细想,不能除23的就都是质数了);若是质数的话其只有自己和1可除,显然要跳出while,还没输出,且其值未变,故直接输出。

可替代标记数组:python很方便的一点在于利用集合的思想,两层for循环 in/not in
strword = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
string充当大集合,运用for 两层In/not in选出在集合中的元素或不在的元素
list也可
字典可用于充当标记数组

lw2num = {'abc':2, 'def':3, 'ghi':4, 'jkl':5,
         'mno':6, 'pqrs':7, 'tuv':8, 'wxyz':9}#省事儿多了,将同value的全写在一个key里
#研究一下ans += [str(lw2num[ls]) for ls in lw2num if s in ls][0]的妙
for ls in lw2num:#依次取出key
	if s in ls:#判断字符是否在这个key
		n=str(lw2num[ls]) 
ans += [n][0] #最后整体输出ans答案

结构体的构建:
class Node(object):
    def __init__(self, val=0):
        self.val = val
        self.next = None
        
初始化head = Node()
head.next = Node(num_list.pop()) 赋值val
head = head.next
print(head.val)

取最小值 MIN = min(dic.values())

Python join(x)方法用于将序列中的元素以指定的字符连接生成一个新的字符串。 注意x只能是序列形的如list
s=''.join(sorted(input()))#妙用字符串''.join()把排列好的一个一个塞进去

eval(n) n得是str类型,返回int类型的值

正则表达式可见目录快捷导航

找规律题比较薄弱
杨辉三角偶数出现的位置是有规律的-1 -12 3 2 4】【2 3 2 4】【...】重复下去
尼科彻斯定理:任何一个整数m的立方都可以写成m个连续奇数之和。也是有规律的,list(range(a * a - a + 1 , a * a + a , 2))所有数都满足
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。
它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。
记住只有4个数[6, 28, 496, 8128]

# 斐波那契数列变换问题
# 第二个月的兔子全体活到第三个月
# 活在第一个月的所有兔子此时都会在第三个月生一次孩子
# 二月的所有兔子,加上之前在一月出生兔子在三月产的孩子,构成了三月的所有兔子
# 即第三项等于前两项之和

查找组成一个偶数最接近的两个素数:首先明确一个数学思想是从中间一半i开始,则n-i和i会更近,如1000  1000-500500差值最小

鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?现要求你打印出所有花一百元买一百只鸡的方式。这种题小学联立解方程问题,可大大缩小复杂度

【动态规划】放苹果问题:把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?注意:如果有7个苹果和3个盘子,(511)和(151)被视为是同一种分法。
放苹果分为两种情况,一种是有盘子为空,一种是每个盘子上都有苹果。
令(m,n)表示将m个苹果放入n个盘子中的摆放方法总数。
1.假设有一个盘子为空,则(m,n)问题转化为将m个苹果放在n-1个盘子上,即求得(m,n-1)即可
2.假设所有盘子都装有苹果,则每个盘子上至少有一个苹果,即最多剩下m-n个苹果,问题转化为将m-n个苹果放到n个盘子上即求(m-n,n)

年月日问题:闰年判断+大小月(左手握拳从右往左数,数完再从右往左数)
能被400整除或者能被4整除但不能被100整除为闰年。二月为29天。一般为28天。

set操作合集:
set() #创建一个空set
set('1')  #输出结果为{'1'}
set('a,b,c,b,c,d')  #输出结果为:{',', 'a', 'b', 'c', 'd'}
set('andjn')  #输出结果为:{'a', 'd', 'j', 'n'}
set(1)#对象不能为数字 error
set()可以装list tuple string dic 
>>> x, y
(set(['b', 'r', 'u', 'o', 'n']), set(['e', 'o', 'g', 'l']))   # 重复的被删除
>>> x & y         # 交集
set(['o'])
>>> x | y         # 并集
set(['b', 'e', 'g', 'l', 'o', 'n', 'r', 'u'])
>>> x - y         # 差集
set(['r', 'b', 'u', 'n'])
python 集合的添加有两种常用方法,分别是add和update。
集合add方法:是把要传入的元素做为一个整个添加到集合中
>>> a.add('python')
集合update方法:是把要传入的元素拆分,做为个体传入到集合中
>>> a.update('python')
>>> a
{'h', 'y', 'e', 'n', 'o', 'p', 't', 'l', 'v'}
集合删除操作方法:remove
>>> a.remove('love')

python实现二维数组:主要有list和numpy.array两种。其实还有matrices,但它必须是2维的,而numpy arrays (ndarrays) 可以是多维的。
两者可以相互转化。
初始化不建议用*3方式 详见https://blog.csdn.net/fuxuemingzhu/article/details/123698243
>>import numpy as np
>>a=[[1,2,3],[4,5,6],[7,8,9]]
>>a
#这个是list的形式
[[1,2,3],[4,5,6],[7,8,9]]
>>type(a)
<type 'list'>
>>a[1][1]
5
>>a[1]
[4,5,6]
>>a[1][:]
[4,5,6]
列表作为数组的优势:支持切片 前闭后开,通过切片,我们可以在任何维度上对数组进行切片。
支持负指数,现在可以使用ARRAY_NAME[-1]获取最后一个元素,类似地,-2提供倒数第二个元素。
list缺点在于不可以直接按坐标x,y取值 说法不一致,自己尝试一下可不可以
>>a[1,1]"""相当于a[1,1]被认为是a[(1,1)],不支持元组索引"""
Traceback (most recent call last):
 File "", line 1, in <module>
TypeError: list indices must be integers, not tuple
>>a[:,1]
Traceback (most recent call last):
 File "", line 1, in <module>
TypeError: list indices must be integers, not tuple

#numpy.array
array=([[1,2,3],
    [4,5,6],
    [7,8,9]])
>>b[1][1]
5
>>b[1]
array([4,5,6])
>>b[1][:]
array([4,5,6])
>>b[1,1]
5
>>b[:,1]
array([2,5,8])

list转化为array
#将list转化为numpy.array
>>b=np.array(a)"""List to array conversion"""
>>type(b)
<type 'numpy.array'>

#matrix
matrix = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
matrix[2][2] = 9
matrix = [[0 for i in range(3)] for i in range(3)]
matrix.append([1,1,1])

list中间插入:
方法一:++切片 
遵循前闭后开,为负数也一样,例如
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9][-6::-1] ## 注意这个不等于[-6:-1],区别是这里是::(两个冒号),两个冒号后连接的是步长
输出[4, 3, 2, 1, 0]可得-6闭,故第一个和第二个索引依然是前闭后开

c = a[:3] + b + a[3:]
方法二:list.insert(index, obj)
fruit = ['pineapple','pear']
fruitlist = ['grape', 'uuu', 'ccc']
for x in fruitlist:
    fruit.insert(len(fruit),x) 

回文串判断:sub_string == sub_string[::-1]

#正则表达式复习
re.sub(r'[0-9]', '*', s)
re.sub(r'[a-z]', '*', s)
re.sub(r'[A-Z]', '*', s)
re.sub(r'[A-Za-z]', '*', s)
re.sub(r'[0-9A-Za-z]', '*', s)
re.sub(r'[0-9]+', '*', s) #这句话则表示匹配多个连续的数字,并将多个连续的数字替换为一个星号 
re.sub(r'[^0-9]+', '*', s) #这句话则表示匹配多个连续的非数字,并将多个连续的非数字替换为一个星号 
re.sub(r'[ ]+', ' ', s1)#去除多余的空格
re.sub(r'@[A-Za-z]+', '', s)#去除以 @ 开头的英文单词
re.sub(r'[0-9A-Za-z]+?', '', s)#?结尾的
re.sub(r'http[:.]+\S+', '', s)#[:.]把:.作为一个整体 :或者.有1~n个都能匹配

re.Match 对象提供了用于取回有关搜索及结果信息的属性和方法:
span() 返回的元组包含了匹配的开始和结束位置
.string 返回传入函数的字符串
group() 返回匹配的字符串部分 一般是group(0) 未取名时
# 将匹配的数字乘以 2
def double(matched):#matched是re.match对象
    value = int(matched.group('value'))
    return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P\d+)', double, s))

保留几位小数:
方法一:format函数
>>> print('{:.3f}'.format(1.23456))
1.235
>>> print(format(1.23456, '.2f'))
1.23

方法二:’%.xf’方法
>>> print('%.2f' % 1.23456)
1.23

多输入方式:
while(1):
    try:
        n=int(input())
     except EOFError:
        break   

str->int:invalid literal for int() with base 10解决方法
明明确实是纯数字组成的串却还是报这个错,直接不管
try:
	n=int(temp)
except ValueError:
	pass


string index out of range解决方法:
打印出来确实是str类型但是就是取其0下标的字符,运行则报这个错,采用切片法 s[0:1]不再报错

局部变量,全局变量相关问题:
1)如果局部要对全局变量修改,应在局部声明该全局变量。 
count = 0
def global_test():
    global count
    count += 1
    print(count)
global_test()

2)如果局部不声明全局变量,并且不修改全局变量,则可以正常使用。
count = 0
def global_test():
    print(count)
global_test()

3nonlocal声明的变量不是局部变量,也不是全局变量,而是外部嵌套函数内的变量。
def nonlocal_test():
    count = 0
    def test2():
        nonlocal count
        count += 1
        return count
    return test2
 
val = nonlocal_test()
print(val())
print(val())
print(val())

坑是真的坑,千万不要用len作变量,否则再用len()函数会报错int' object is not callable

正则表达式

[原文链接:https://blog.csdn.net/jackandsnow/article/details/103885422]
首先import re
re.sub()方法,该函数主要用于替换字符串中的匹配项。含有5个参数,下面进行一一说明(加粗的为必须参数):
(1)pattern:该参数表示正则中的模式字符串;
(2)repl:该参数表示要替换的字符串(即匹配到pattern后替换为repl),也可以是个函数;
(3)string:该参数表示要被处理(查找替换)的原始字符串;

(4)count:可选参数,表示是要替换的最大次数,而且必须是非负整数,该参数默认为0,即所有的匹配都会被替换;
(5)flags:可选参数,表示编译时用的匹配模式(如忽略大小写、多行模式等),数字形式,默认为0。
例:re.sub(r’[0-9]', ‘*’, s)
链接:更多正则表达式学习笔记


HJ7 取近似值

def main():
    num =float(input())
    num_=num%1
    #print(num_)
    if (num_ < 0.5):
        print(int(num-num_))
    else:
        print(int(num-num_ + 1))

if __name__ == '__main__':
    main()

HJ9 提取不重复的整数
输入一个 int 型整数,按照从右向左的阅读顺序,返回一个不含重复数字的新的整数。
保证输入的整数最后一位不是 0 。

def main():
    num=input()
    list_num = []
    for item in num:
        #print(item)
        list_num.append(item)
    #print(list_num)
    list_num.reverse()
    #print(list_num)
    outcome=[]
    for i in list_num:
        if i not in outcome:
            outcome.append(i)
    print(''.join(outcome))
if __name__ == '__main__':
    main()

HJ46 截取字符串
输入一个字符串和一个整数 k ,截取字符串的前k个字符并输出

def main():
    num=input()
    n=input()
    i=0
    for j in range(0,int(n)):
        if(i<int(n)):
            print (num[i],end='')
        i=i+1

if __name__ == '__main__':
    main()

HJ58 输入n个整数,输出其中最小的k个

def main():
    str=input()
    list_=str.split(' ')
    n=int(list_[0])
    k=int(list_[1])
    str = input()
    list_num = str.split(' ')
    list_num=[int(i) for i in list_num]
    list_num.sort()
    for j in range(0,k):
        print(list_num[j],end=' ')
if __name__ == '__main__':
    main()

HJ101 输入整型数组和排序标识,对其元素按照升序或降序进行排序

def main():
    n=int(input())
    num=[int(i) for i in input().split(' ')]
    order=input()
    parameter=False
    if(order=='1'):
        parameter=True
    num.sort(reverse=parameter)
    for i in range(0,n):
        print(num[i],end=' ')
if __name__ == '__main__':
    main()

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

def main():
    str=input()
    str=str.split(' ')
    word=str[len(str)-1]
    print(len(word))
if __name__ == '__main__':
    main()

HJ2 计算某字符出现次数(不区分大小写字母)

def main():
    str=input()
    letter=input()
    count=0
    #print(len(str))
    for i in range(0,len(str)):
        n=ord(letter)
        n_=ord(str[i])
        if(letter==str[i]):
            count += 1
        elif (n>=65 and n<=90 and n+32==n_):
            count += 1
        elif (n>= 97 and n <= 122 and n -32 ==n_):
            count += 1
    print(count)
if __name__ == '__main__':
    main()

HJ4 字符串分隔
•输入一个字符串,请按长度为8拆分每个输入字符串并进行输出;
•长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。

def main():
    str=input()
    if(str==''):
        return
    n=len(str)%8
    #print(n)
    if(n):
        count=8-n
        for i in range(0,count):
            str+='0'
    #print(str)
    n = int(len(str) / 8)
    for j in range(0,n):
        print(str[j*8:j*8+8])

if __name__ == '__main__':
    main()

HJ5 进制转换

def main():
    num16=input()
    num16=int(num16,0)
    print(num16)

if __name__ == '__main__':
    main()

HJ6 质数因子

def main():#第一遍不通过的样例,显然打表对于这么大的范围时间复杂度太高了,而且有一个样例很大的不通过
    n=int(input())
    prime=[2,3,5,7]#prime table
    for i in range(11,100000):
        for j in range(2,1000):
            if(i%j==0):
                break
        prime.append(i)
    k=0
    while(n and k<len(prime)):
        if(n%prime[k]==0):
            print(prime[k],end=' ')
            n/=prime[k]
        else :
            k+=1
                    
if __name__ == '__main__':
    main()

#更正:先找因子再判断是否是质数 还是超时!!!
def isPrime(n):
	prime=[2,3,5,7,11,13,17,19]
	if(n in prime):
		return 1
    for i in range(2,int(n**0.5)):
        if(n%i==0):
            return 0
    return 1

def main():
    n=int(input())
    k=2
    while (n):
        if(n%k==0 and isPrime(k)):
            print(k,end=' ')
            n/=k
        else:
            k+=1

if __name__ == '__main__':
    main()

#qaq 看看别人怎么写的不超时 
import math
n = int(input())
for i in range(2, int(math.sqrt(n))+1):
    while n % i == 0:
        print(i, end=' ')
        n = n // i
if n > 2:
    print(n)

结论:输在了数学结论上,质因子(或质因数)在数论里是指能整除给定正整数的质数。根据算术基本定理,不考虑排列顺序的情况下,每个正整数都能够以唯一的方式表示成它的质因数的乘积。故应该得到如果它能除一个质数,则后续因子均为质因数,且只有这一种结果。而数要么是质数,要么不是质数,如果不是则一定可以除2/3,因为能除2的倍数就能除2,能除3的倍数就能除3,(细想,不能除2和3的就都是质数了);若是质数的话其只有自己和1可除,显然要跳出while,还没输出,且其值未变,故直接输出。

HJ13 句子逆序

def main():
    str=input()
    str=str.split(' ')
    str.reverse()
    for item in str:
        print(item,end=' ')
if __name__=='__main__':
    main()

HJ12 字符串反转
接受一个只包含小写字母的字符串,然后输出该字符串反转后的字符串。(字符串长度不超过1000)
输入描述:
输入一行,为一个只包含小写字母的字符串。
输出描述:
输出该字符串反转后的字符串。

def main():
    str=input()
    list_=[]
    for item in str:
        list_.append(item)
    list_[:]=list_[::-1]
    for j in list_:
        print(j,end='')
if __name__=='__main__':
    main()

#更牛逼的版本
print(input()[::-1])#啥反转都可以用这个

HJ10 字符个数统计
自己想的都是标记数组之类的,不够效率;python很方便的一点在于利用集合的思想,两层for循环 in/not in可替代标记数组

s = input()
res = ""
for i in s:
    if i not in res:
        res += i      
print(len(res))

while True:
    try:
        bb = []
        aa =input()
        for j in aa:    #遍历字符内元素
            if j not in bb:  #在列表bb搜索j
                bb.append(j)
        print(len(bb))
    except:
        break
        

HJ8 合并表记录

def main():
    n=input()
    dic={}
    for i in range(0,int(n)):
        str=input().split(' ')
        key_=int(str[0])
        value_=int(str[1])
        if(not key_ in dic.keys()):
            dic[key_]=value_
        else:
            dic[key_]+=value_
    dic=sorted(dic.items(),key=lambda x:x[0])
    
    for item in dic:
        print(item[0],item[1])
    #print(dic)
if __name__=='__main__':
    main()

HJ14 字符串排序

def main():
    n=int(input())
    str=[]
    for i in range(0,n):
        str.append(input())
    str.sort()
    for item in str:
        print(item)
if __name__=='__main__':
    main()

HJ15 求int型正整数在内存中存储时1的个数
其实就是转二进制再看有多少个1

def main():
    n=int(input())
    str=bin(n)
    print(str.count('1'))
if __name__=='__main__':
    main()

HJ21 简单密码
现在有一种密码变换算法。
九键手机键盘上的数字与字母的对应: 1–1, abc–2, def–3, ghi–4, jkl–5, mno–6, pqrs–7, tuv–8 wxyz–9, 0–0,把密码中出现的小写字母都变成九键键盘对应的数字,如:a 变成 2,x 变成 9.
而密码中出现的大写字母则变成小写之后往后移一位,如:X ,先变成小写,再往后移一位,变成了 y ,例外:Z 往后移是 a 。
数字和其它的符号都不做变换。
输入范围1≤n≤100

def main():#感觉这方法好笨啊,看看别人咋写的
    dic={'a':'2','b':'2','c':'2','d':'3','e':'3','f':'3','g':'4','h':'4',
         'i':'4','j':'5', 'k':'5', 'l':'5', 'm':'6','n':'6',
        'o':'6','p':'7','q':'7','r':'7','s':'7',
         't':'8','u':'8','v':'8','w':'9','x':'9','y':'9','z':'9',}
    str=input()
    for i in range(0,len(str)):
        n=ord(str[i])
        if(str[i]=='1'):
            print('1',end='')
        elif(str[i]=='0'):
            print('0',end='')
        elif(n>=65 and n<97):
            n+=33
            if(n>=123):
                n-=26
            print(chr(n),end='')
        elif(n>=97 and n<123):
            print(dic[str[i]],end='')
        else:
            print(str[i],end='')
            
if __name__=='__main__':
    main()

#别人写的好精简
st = input().strip()
lw2num = {'abc':2, 'def':3, 'ghi':4, 'jkl':5,
         'mno':6, 'pqrs':7, 'tuv':8, 'wxyz':9}#省事儿多了
ans = ''
for s in st:
    if s.isupper():
        if s != 'Z':
            ans += chr(ord(s) + 33)
        else:
            ans += 'a'
    elif s.islower():
        ans += [str(lw2num[ls]) for ls in lw2num if s in ls][0]
    else:
        ans += s
print(ans)

#研究一下ans += [str(lw2num[ls]) for ls in lw2num if s in ls][0]的妙
for ls in lw2num:#取出key
	if s in ls:#判断字符是否在这个key
		n=str(lw2num[ls]) 
ans += [n][0] #最后整体输出ans答案

HJ22 汽水瓶
某商店规定:三个空汽水瓶可以换一瓶汽水,允许向老板借空汽水瓶(但是必须要归还)。
小张手上有n个空汽水瓶,她想知道自己最多可以喝到多少瓶汽水。
数据范围:输入的正整数满足 1≤n≤100
注意:本题存在多组输入。输入的 0 表示输入结束,并不用输出结果。
输入描述:
输入文件最多包含 10 组测试数据,每个数据占一行,仅包含一个正整数 n( 1<=n<=100 ),表示小张手上的空汽水瓶数。n=0 表示输入结束,你的程序不应当处理这一行。
输出描述:
对于每组测试数据,输出一行,表示最多可以喝的汽水瓶数。如果一瓶也喝不到,输出0。

def main():
    while(1):
        n_=int(input())
        if(n_):
            judge(n_)
        else:
            exit()
def judge(n_):
    drank=0
    water=0
    bottle=n_
    while(bottle):
        water+=int(bottle/3)
        bottle=bottle%3
        drank+=water
        #print('water',water,'bottle',bottle,'drank',drank)
        bottle+=water
        water=0
        #print('water',water,'bottle',bottle,'drank',drank)
        if((bottle+1)<3):
            print(drank)
            bottle=0
        elif(bottle==2):
            drank+=1
            print(drank)
            bottle=0

if __name__=='__main__':
    main()

HJ23 删除字符串中出现次数最少的字符

def main():
    string=input()
    n=0
    min=50
    total=0
    letter=[]
    for i in range(0,len(string)):
        n=string.count(string[i])
        total+=n
        if(n<=min):
            min=n 
            letter.append(string[i])
        
    for l in letter:
        if(string.count(l)==min):
            string=string.replace(l,'')
    print(string)
if __name__=='__main__':
    main()
#感觉还是有多余操作,看看别人咋写的
s = input()
dic = {}#字典还是妙啊,类似于标记数组
for i in s:
    if i in dic:
        dic[i] +=1
    else:
        dic[i] = 1
MIN = min(dic.values())

for i in s :
    if dic[i] == MIN:
        s = s.replace(i,'')
print(s)

HJ31 单词倒排
对字符串中的所有单词进行倒排。
说明:
1、构成单词的字符只有26个大写或小写英文字母;
2、非构成单词的字符均视为单词间隔符;
3、要求倒排后的单词间隔符以一个空格表示;如果原字符串中相邻单词间有多个间隔符时,倒排转换后也只允许出现一个空格间隔符;
4、每个单词最长20个字母;
数据范围:字符串长度满足 1≤n≤10000

补充的正则表达式见补充合集


def main():
    string=input()
    stack=[]
    sen=''
    for i in range(0,len(string)):
        n=ord(string[i])
        if(n>=65 and n<=90):
            sen+=string[i]
        elif(n>=97 and n<=122):
            sen+=string[i]
        else:
            stack.append(sen)
            sen=''
            stack.append(' ')
    
    stack.append(sen)    
    stack.reverse()
    for item in stack:
        print(item,end='')
            
if __name__=='__main__':
    main()
            
 #人才辈出的各种更简单的解法:
mystr = input()
strword = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
for i in mystr:
    if i not in strword:
        mystr = mystr.replace(i," ")
mylist = mystr.split(" ")
mylist.reverse() #串可以直接逆
for i in mylist:
    print(i,end=" ")
    
#正则表达式更猛 
import re
a = re.sub('[\W]',' ',input())
a = a.strip(' ').split(' ')
print(' '.join(a[::-1]))
#or
import re
a = input()
a1 = re.sub('[^A-Za-z0-9_]', ' ', a)
a1 = a1.strip(' ')
a1 = a1.split(' ')

for i in a1[::-1]:
    print(i, end = ' ')
    
#isalpha()函数 是字母返回true
m=input()
n='' 
for k in m: 
    if k.isalpha():
        n+=k 
    else:
        n+=" "  
li=n.split()[::-1]
s='' 
for i in li:
    s+=i+" " 
print(s)

HJ34 图片整理
Lily上课时使用字母数字图片教小朋友们学习英语单词,每次都需要把这些图片按照大小(ASCII码值从小到大)排列收好。请大家给Lily帮忙,通过代码解决。
Lily使用的图片使用字符"A"到"Z"、“a"到"z”、"0"到"9"表示。
数据范围:每组输入的字符串长度满足 1≤n≤1000

s=''.join(sorted(input()))#妙用字符串''.join()
print(s)

HJ35 蛇形矩阵
蛇形矩阵是由1开始的自然数依次排列成的一个矩阵上三角形。
例如,当输入5时,应该输出的三角形为:
1 3 6 10 15
2 5 9 14
4 8 13
7 12
11
输入描述:输入正整数N(N不大于100)
输出描述:输出一个N行的蛇形矩阵。

#没观察出来是啥,这种题只能自己找行列ij的规律,以下是大佬解法
n = int(input().strip())
for i in range(1,n+1) :
    for j in range(i,n+1) :
        print(int(((j+j**2)/2)-i+1),end = ' ') #5/2=3
    # 一次循环结束后打印空,用作换行
    print()

HJ37 统计每个月兔子的总数
有一种兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子。
例子:假设一只兔子第3个月出生,那么它第5个月开始会每个月生一只兔子。
一月的时候有一只兔子,假如兔子都不死,问第n个月的兔子总数为多少?
数据范围:输入满足 1≤n≤31
输入描述:
输入一个int型整数表示第n个月
输出描述:
输出对应的兔子总数

# 斐波那契数列变换问题
# 
# 第二个月的兔子全体活到第三个月
# 活在第一个月的所有兔子此时都会在第三个月生一次孩子
# 二月的所有兔子,加上之前在一月出生兔子在三月产的孩子,构成了三月的所有兔子
# 即第三项等于前两项之和

# 递归法
a = int(input())
count = 0
def fun(n):
    if n<=2:
        return 1
    else:
        return fun(n-1) + fun(n-2)
print(fun(a))

# 循环列表法
a = int(input())
a1,a2,a3 = 1,1,2    # 已知前三个月的兔子数
for i in range(a-2):
    a3 = a1 + a2
    a1 = a2
    a2 = a3
print(a3)

HJ51 输出单向链表中倒数第k个结点
要求:
(1)正序构建链表;
(2)构建后要忘记链表长度。
显然,这道题不允许用自带的函数作弊。

#妙啊
while True:
    try:
        count, num_list, k = int(input()), [int(x) for x in input().split()], int(input())
        print(num_list[-k] if k else 0)
    except EOFError:
        break
#来个正儿八经的 结构体的构建
class Node(object):
    def __init__(self, val=0):
        self.val = val
        self.next = None
        
while True:
    try:
        head = Node()
        count, num_list, k = int(input()), list(map(int, input().split())), int(input())
        while k:
            head.next = Node(num_list.pop())
            head = head.next
            k -= 1
        print(head.val)
    except EOFError:
        break

HJ53 杨辉三角的变形
以上三角形的数阵,第一行只有一个数1,以下每行的每个数,是恰好是它上面的数、左上角数和右上角的数,3个数之和(如果不存在某个数,认为该数就是0)。
求第n行第一个偶数出现的位置。如果没有偶数,则输出-1。例如输入3,则输出2,输入4则输出3,输入2则输出-1。
数据范围:1≤n≤10 ^9
牛客华为机试题刷题笔记总结[103题更新完毕才收尾,建议关注收藏]_第1张图片

n = int(input())
if n ==1 and n==2:
    print(-1)
elif n%2 == 1:
    print(2)
elif n%4 == 0:
    print(3)
else:
    print(4)

HJ54 表达式求值

 while True:
  try:
    n = input()
    print(eval(n))
  except:
    break

HJ56 完全数计算
完全数(Perfect number),又称完美数或完备数,是一些特殊的自然数。
它所有的真因子(即除了自身以外的约数)的和(即因子函数),恰好等于它本身。
例如:28,它有约数1、2、4、7、14、28,除去它本身28外,其余5个数相加,1+2+4+7+14=28。

while True:
    try:
        nums = int(input())
        count = 0
        plus = 0
        for num in range(2, nums + 1):
            for i in range(1, int(num ** 0.5) + 1):
                if num % i == 0:
                    if i == 1:
                        plus += i
                    else:
                        plus += i
                        plus += num // i
            if plus == num:
                count += 1
            plus = 0
        print(count)
    except:
        break

#其实还有更快的,就是记住只有4个数[6, 28, 496, 8128]

HJ60 查找组成一个偶数最接近的两个素数
首先明确一个数学思想是从中间一半i开始,则n-i和i会更近
如1000 1000-500与500差值最小

while True:
    try:
        n = int(input())
        prime = []
        for i in range(int(n/2), 1,-1):
            for x in range(2,i):
                if i%x == 0 or (n-i)%x == 0:
                    break
            else:
                prime.append(i)
        print(prime[0])
        print(n-prime[0])
    except:
        break

HJ72 百钱买百鸡问题
公元五世纪,我国古代数学家张丘建在《算经》一书中提出了“百鸡问题”:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。百钱买百鸡,问鸡翁、鸡母、鸡雏各几何?现要求你打印出所有花一百元买一百只鸡的方式。
方法一:暴力遍历
直观的我们可以看出公鸡最多20只就超出了价格,母鸡最多34只就超出价格,小鸡100只超出了数量范围,因此在这个三个范围内进行暴力遍历尝试
方法二:解方程联立
假定公鸡、母鸡、小鸡数量为a,b,c则有 a+b+c=100 , 5a+3b+c/3=100,消去c可知b = 25-7a/4
因此我么可以知道a必须是4的倍数,而且b如果为正数的话要求a最大只能取3,根据这个结果进行循环遍历,得到输出即可

while True:
    try:
        ppp = input()
        for i in range(4):        # 数学推导,公鸡只能取0,4,8,12只
            a = 4*i
            b = 25-7*i
            c = 100-a-b
            print(a,b,c)
    except:
        break

HJ61 放苹果
把m个同样的苹果放在n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?
注意:如果有7个苹果和3个盘子,(5,1,1)和(1,5,1)被视为是同一种分法。
数据范围:0≤m≤10 ,1≤n≤10 。

'''
放苹果分为两种情况,一种是有盘子为空,一种是每个盘子上都有苹果。
令(m,n)表示将m个苹果放入n个盘子中的摆放方法总数。
1.假设有一个盘子为空,则(m,n)问题转化为将m个苹果放在n-1个盘子上,即求得(m,n-1)即可
2.假设所有盘子都装有苹果,则每个盘子上至少有一个苹果,即最多剩下m-n个苹果,问题转化为将m-n个苹果放到n个盘子上
即求(m-n,n)
'''
def f(m,n):
    if m<0 or n<0:
        return 0
    elif m==1 or n==1:
        return 1
    else:
        return f(m,n-1)+f(m-n,n)
while True:
    try:
        m,n=map(int,input().split())
        print(f(m,n))
    except:
        break

HJ73 计算日期到天数转换:计算是这一年的第几天。
补充知识:闰年判断+大小月(左手握拳从右往左数)
能被400整除或者能被4整除但不能被100整除为闰年。二月为29天。一般为28天。

str=input().split(' ')
year=int(str[0])
month=int(str[1])
day=int(str[2])
list=[31,28,31,30,31,30,31,31,30,31,30,31]
if(year%4==0 and year%100)or(year%400==0):
    list[1]=29
num=0
for i in range(0,month-1):
    num+=list[i]
num+=day
print(num)

HJ76 尼科彻斯定理
验证尼科彻斯定理,即:任何一个整数m的立方都可以写成m个连续奇数之和。
例如:
1^3=1
2^3=3+5
3^3=7+9+11
4^3=13+15+17+19
输入一个正整数m(m≤100),将m的立方写成m个连续奇数之和的形式输出。
数据范围:1≤m≤100

n=int(input())
total=n**3
sum=0

for i in range(0,total,1):
    if(i%2):
        sum=n*i+n*(n-1)
        if(sum==total):
            for j in range(0,n):
                print(eval('i+j*2'),end='')
                if(j!=n-1):
                    print('+',end='')
            break
#大神的解法 妙啊
try:
    while True:
        a = int(input())
        ary = list(range(a * a - a + 1 , a * a + a , 2))#发现了规律,所有数都满足
        print("+".join(map(str, ary)))
except EOFError:
    pass

HJ80 整型数组合并
题目标题:
将两个整型数组按照升序合并,并且过滤掉重复数组元素。
输出时相邻两数之间没有空格。
输入描述:
输入说明,按下列顺序输入:
1 输入第一个数组的个数
2 输入第一个数组的数值
3 输入第二个数组的个数
4 输入第二个数组的数值

首先已知老方法in list判断是不是重复的,现学一下set的用法,见补充

#set
n=input()
a=set([int(i)for i in input().split(' ')])
n=input()
b=set([int(i)for i in input().split(' ')])
c=sorted(a|b)
for i in c:
    print(i,end='')
#list
n=input()
a=[int(i)for i in input().split(' ')]

n=input()
b=[int(i)for i in input().split(' ')]
a+=b
b=[]
for i in a:
    if i not in b:
        b.append(i)
b.sort()
for i in b:
    print(i,end='')

HJ81 字符串字符匹配
输入两个字符串。第一个为短字符串,第二个为长字符串。两个字符串均由小写字母组成。返回true false

substring=input()
string=input()
for i in substring:
    if(i not in string):
        print('false')
        substring=''
        break
if(substring!=''):
    print('true')

HJ83 二维数组操作

#看清题目,人家只用判界就行了。。。
def init_(row,col,array):
    if(row>9 or col>9):
        print (-1)
        return
    for i in range(0,row):
        temp=[]
        for j in range(0,col):
            temp.append(0)
        array.append(temp)
    #print(array)
    print (0)
    
def swap(x1,y1,x2,y2,array):
    if(x1>=9 or x2>=9 or y1>=9 or y2>=9 or x1>=row or x2>=row or y1>=col or y2>=col):
        print(-1)
        return
    temp=array[x1][y1]
    array[x1][y1]=array[x2][y2]
    array[x2][y2]=temp
    print (0)
    
def add_x(n,array):
    if(n>9 or n>row or row+1>9):
        print (-1)
        return
    list_=[]
    for i in range(0,col):
        list_.append(0)
    array=array[0:n-1]+list_+array[n:col-2]
    print (0)

def add_y(n,array):
    k=n-1
    if(k>=9 or n>=col or col+1>9 ):
        print (-1)
        return

    print (0)

def find(x,y,array):
    if(x>row-1 or y>col-1):
        print (-1)
        return
    print (0)
    
if __name__=='__main__':
    array=[]
    while(1):
        try:
            n=input().split(' ')
            row=int(n[0])
            col=int(n[1])
            init_(row,col,array)
            n=[int(i) for i in input().split(' ')]
            swap(n[0],n[1],n[2],n[3],array)
            n=int(input())
            add_x(n,array)
            n=int(input())
            add_y(n,array)
            n=[int(i) for i in input().split(' ')]
            x1=n[0]
            x2=n[1]
            find(x1,x2,array)
        except EOFError:
            break

HJ84 统计大写字母个数
很简单 代码略

HJ85 最长回文子串
给定一个仅包含小写字母的字符串,求它的最长回文子串的长度。
所谓回文串,指左右对称的字符串。
所谓子串,指一个字符串删掉其部分前缀和后缀(也可以不删)的字符串
输入描述:
输入一个仅包含小写字母的字符串
输出描述:
返回最长回文子串的长度

#总感觉写不下来,看看大神的
def cal(s):
    for length in range(len(s),-1,-1): #长度递减
        for index in range(0,len(s)-length+1):
            sub_string = s[index:length+index]
            if sub_string == sub_string[::-1]: #这个属实妙的没想到
                return len(sub_string)
while True:
    try:
        a = input()
        if a:
            print(cal(a))  
    except:
        break

HJ86 求最大连续bit数
easy,代码略

HJ87 密码强度等级
密码按如下规则进行计分,并根据不同的得分为密码进行安全等级划分。

一、密码长度:
5 分: 小于等于4 个字符
10 分: 5 到7 字符
25 分: 大于等于8 个字符

二、字母:
0 分: 没有字母
10 分: 密码里的字母全都是小(大)写字母
20 分: 密码里的字母符合”大小写混合“

三、数字:
0 分: 没有数字
10 分: 1 个数字
20 分: 大于1 个数字

四、符号:
0 分: 没有符号
10 分: 1 个符号
25 分: 大于1 个符号

五、奖励(只能选符合最多的那一种奖励):
2 分: 字母和数字
3 分: 字母、数字和符号
5 分: 大小写字母、数字和符号

最后的评分标准:

= 90: 非常安全
= 80: 安全(Secure)
= 70: 非常强
= 60: 强(Strong)
= 50: 一般(Average)
= 25: 弱(Weak)
= 0: 非常弱(Very_Weak)

对应输出为:
VERY_SECURE
SECURE
VERY_STRONG
STRONG
AVERAGE
WEAK
VERY_WEAK

请根据输入的密码字符串,进行安全评定。

注:
字母:a-z, A-Z
数字:0-9
符号包含如下: (ASCII码表可以在UltraEdit的菜单view->ASCII Table查看)
!"#$%&'()*+,-./ (ASCII码:0x21~0x2F)
:;<=>?@ (ASCII码:0x3A~0x40)
[]^_` (ASCII码:0x5B~0x60)
{|}~ (ASCII码:0x7B~0x7E)

s=input()
l=len(s)
sum=0
if(l<=4):
    sum+=5
elif(l>=5 and l<=7):
    sum+=10
else:
    sum+=25
upper=0
lower=0
num=0
other=0
for i in range(0,len(s)):
    if(s[i].isupper()):
        upper=1
    elif(s[i].islower()):
        lower=1
    elif(s[i].isdigit()):
        num+=1
    else:
        other+=1
if(upper==0):
    if(lower!=0):
        sum+=10
else:
    if(lower!=0):
        sum+=20
    else:
        sum+=10
if(num):
    if(num==1):
        sum+=10
    else:
        sum+=20
if(other):
    if(other==1):
        sum+=10
    else:
        sum+=25
if(num):
    if(upper or lower):
        sum+=2
        if(other):
            sum+=1
            if(lower and upper):
                sum+=2
if(sum>=90):
    print('VERY_SECURE')
elif(sum>=80):
    print('SECURE')
elif(sum>=70):
    print('VERY_STRONG')
elif(sum>=60):
    print('STRONG')
elif(sum>=50):
    print('AVERAGE')
elif(sum>=25):
    print('WEAK')
else:
    print('VERY_WEAK')
    

HJ91 走方格的方案数
请计算n*m的棋盘格子(n为横向的格子数,m为竖向的格子数)从棋盘左上角出发沿着边缘线从左上角走到右下角,总共有多少种走法,要求不能走回头路,即:只能往右和往下走,不能往左和往上走。
注:沿棋盘格之间的边缘线行走

def sum(row,col): #从大规模往小规模里缩
    if(row==0 or col==0):#若某一边为0时则压成一条直线,故仅一种
        return 1
    else:
        return sum(row-1,col)+sum(row,col-1)
if __name__=='__main__':
    s=input().split(' ')
    row=int(s[0])
    col=int(s[1])
    print(sum(row,col))

HJ94 记票统计
简单,代码略,用字典就可

HJ96 表示数字
将一个字符串中所有的整数前后加上符号“*”,其他字符保持不变。连续的数字视为一个整数。

import re
def add(matched):
    #print(matched.group(0))
    return '*'+str(matched.group(0))+'*'
if __name__=='__main__':
    s=input()
    print(re.sub(r'[\d]+',add,s))

HJ97 记负均正
round(x,1)四舍五入1位小数,其他简单,略

HJ99 自守数
自守数是指一个数的平方的尾数等于该数自身的自然数。例如:25^2 = 625,76^2 = 5776,9376^2 = 87909376。请求出n(包括n)以内的自守数的个数

n=int(input())
c=0
for i in range(0,n+1):
    new=str(i**2)
    k=new.rfind(str(i))
    if(k!=-1):
        if(k+len(str(i))==len(new)):
            c+=1
    #print(new,str(i),new.find(str(i)))
print(c)

HJ100 等差数列
(从 2 开始的 3 为公差的等差数列)输出求等差数列前n项和
简单,代码略

HJ102 字符统计
输入一个只包含小写英文字母和数字的字符串,按照不同字符统计个数由多到少输出统计结果,如果统计的个数相同,则按照ASCII码由小到大排序输出。

s=input()
dic={}
for i in range(0,len(s)):
    if(s[i].isalpha()):
        if(s[i] not in dic.keys()):
            dic[s[i]]=1
        else:
            dic[s[i]]+=1
    if(s[i].isdigit()):
        if(s[i] not in dic.keys()):
            dic[s[i]]=1
        else:
            dic[s[i]]+=1
l=sorted(dic.items(),key= lambda x:(-x[1],x[0]))
for j in l:
    print(j[0],end='')

HJ105 记负均正II

sum=0
minus=0
num=0
while(1):
    try:
        n=int(input())
        if(n>=0):
            sum+=n
            num+=1
        else:
            minus+=1
        #print(n,' ',sum)
    except EOFError:
        break   
print(minus)
#print(n)
n-=minus
if(sum==0):
    print(0.0)
else:
    print(round(sum/num,1))
        

HJ106 字符逆序
非常简单。。。代码略过

HJ108 求最小公倍数

最小公约数和最小公倍数

while True:#超时版。。。
    try:
        A, B = map(int, input().split())
        M = max(A, B)
        S = int(A * B)
        for i in range(M, S + 1):
            if i % A == 0 and i % B == 0:
                print(i)
                break 
    except:
        break
def lcm(a: int, b: int):#大佬版 跟最小公约数也是扯上关系的
    def gcd(a: int, b: int):
        if b == 0:
            return a
        else:
            return gcd(b, a % b)
        
    return int((a * b) / gcd(a, b))

a, b = map(int, input().split())
print(lcm(a, b))

HJ16 购物单

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个物品要么放入背包,要么不放入背包。

dp = [[0]*(n+1) for _ in range(m+1)]#0~m _是用不上的循环序号 n+1个0 即创造m行n+1列值为0的矩阵
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背包一样了。附件不能单独出现,要依赖于主件。对应于背包问题,主件的个数就是物品的个数,考虑每个主件时要考虑可能出现的情况。考虑每个物品时要考虑每种可能出现的情况,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)
模版:
dp = [[0]*(n+1) for _ 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])
实现:
n, m = map(int,input().split())
primary, annex = {}, {}
for i in range(1,m+1):
    x, y, z = map(int, input().split())
    if z==0:#主件
        primary[i] = [x, y]
    else:#附件
        if z in annex:#第二个附件
            annex[z].append([x, y])
        else:#第一个附件
            annex[z] = [[x,y]]
m = len(primary)#主件个数转化为物品个数
dp = [[0]*(n+1) for _ in range(m+1)]
w, v= [[]], [[]]
for key in primary:
    w_temp, v_temp = [], []
    w_temp.append(primary[key][0])#1、主件
    v_temp.append(primary[key][0]*primary[key][1])
    if key in annex:#存在主件
        w_temp.append(w_temp[0]+annex[key][0][0])#2、主件+附件1
        v_temp.append(v_temp[0]+annex[key][0][0]*annex[key][0][1])
        if len(annex[key])>1:#存在两主件
            w_temp.append(w_temp[0]+annex[key][1][0])#3、主件+附件2
            v_temp.append(v_temp[0]+annex[key][1][0]*annex[key][1][1])
            w_temp.append(w_temp[0]+annex[key][0][0]+annex[key][1][0])#3、主件+附件1+附件2
            v_temp.append(v_temp[0]+annex[key][0][0]*annex[key][0][1]+annex[key][1][0]*annex[key][1][1])
    w.append(w_temp)
    v.append(v_temp)
for i in range(1,m+1):
    for j in range(10,n+1,10):#物品的价格是10的整数倍
        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])

HJ17 坐标移动
开发一个坐标计算工具, 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)
if __name__=='__main__':注意是两个等号!!老是容易打错

def judge(s):
    for i in range(len(s)):
        if(ord(s[i])>=48 and ord(s[i])<=57):
            continue
        else:
            return 0
    return 1

def main():
    x=0
    y=0
    s=input().split(';')
    
    for item in s:
        if(len(item)<=3):
            temp=item[1:]
            n=judge(temp)
            if(n):
                #print(temp)
                try:
                    n=int(temp)
                except ValueError:
                    pass
               # print(n,type(n))
                
                if(item[0:1]=='A'):
                        x-=n
                elif(item[0:1]=='D'):
                        x+=n
                elif(item[0:1]=='W'):
                        y+=n
                elif(item[0:1]=='S'):
                        y-=n               
    print(str(x)+','+str(y))
    return
    
if __name__ == '__main__':
    main()

HJ20 密码验证合格程序
密码要求:
1.长度超过8位
2.包括大小写字母.数字.其它符号,以上四种至少三种
3.不能有长度大于2的包含公共元素的子串重复 (注:其他符号不含空格或换行)

def judge(s):
    num=0
    upper=0
    lower=0
    other=0
    
    if(len(s)<=8):
        print('NG')
        return
    for i in range(len(s)):
        if(s[i].isdigit()):
            num=1
        elif(s[i].isupper()):
            upper=1
        elif(s[i].islower()):
            lower=1
        elif(s[i]!=' ' and s[i]!='\n'):
            other=1
        
        if(i+3<len(s)):
            sub=s[i:i+3]
            if(s.count(sub)>1):
                #print(i,sub,s.count(sub))
                print('NG')
                return
    if(num+upper+lower+other<3):
        print('NG')
        return
    print('OK')
    return

if __name__=='__main__':
    while(1):
        try:
            s=input()
            judge(s)
        except:
            break

HJ24 合唱队
牛客华为机试题刷题笔记总结[103题更新完毕才收尾,建议关注收藏]_第2张图片

最长递增子序列

此题是最长递增子序列的变体,基本思路是对原序列从左到右和从右到左分别求出到每个元素的最长递增子序列的长度。例如,原序列为长度为N的序列[8,20,12,15,10,9],从左至右的到序列里每个元素的最长递增子序列为l1=[1,2,2,3,2,2],从右至左为l2=[1,4,3,3,2,1],l1+l2=[2,6,5,6,4,3]。那么合唱队最长队伍是L = max(l1+l2)-1,减1是因为计算l1和l2时重复计算了一次元素本身。因此最少出列人数为原序列长度N-L。
关键在于求出l1,l2。可由动态规划求出。用dp[i]表示从左至右到原序列第i个元素的最长递增子序列的长度,从第i个元素往回遍历更新dp[i]的值。由于每个元素都需要往回遍历一次,用二分法代替往回遍历时间复杂度是o(nlogn)
二分法的过程为:首先创建数组arr=[ele_1],ele_1是原序列第一个元素,然后从第二个元素开始从左至右遍历原序列
如果ele_i > max(arr),将ele_i加到arr最后
如果ele_i <= max(arr),用二分法找到arr中第一个比ele_i大(或相等)的元素并用ele_i替换
( 但arr不是最长递增子序列)

Python中的bisect模块可以在列表插入元素之后维持列表的有序状态,而不需要重新对列表排序。bisect有以下6个函数,这6个函数接受相同的参数:
bisect.bisect_left(a, x, lo=0, hi=len(a)):a是列表,x是要插入的元素。函数返回在a中插入x的位置,如果a中已经存x,那么插入的位置在a中最左边的x的前面一位。返回值把列表分成两部分,插入点左侧满足all(val < x for val in a[lo:i]),插入点右侧满足all(val >= x for val in a[i:hi])。
bisect.bisect_right(a, x, lo=0, hi=len(a)):与bisect.bisect_left的不同点在于,如果a中已经存x,那么插入的位置在a中最右边的x的后面一位。
bisect.bisect(a, x, lo=0, hi=len(a)):与bisect.bisect_right相同。返回值把列表分成两部分,插入点左侧满足all(val <= x for val in a[lo:i+1]),插入点右侧满足all(val > x for val in a[i+1:hi])。
bisect.insort_left(a, x, lo=0, hi=len(a)):返回插入元素后的列表。先使用bisect.bisect_left获得插入元素的位置,然后在该位置插入元素并返回列表。等价于a.insert(bisect.bisect_left(a, x, lo, hi), x)。
bisect.insort_right(a, x, lo=0, hi=len(a)):等价于a.insert(bisect.bisect_right(a, x, lo, hi), x)。
bisect.insort(a, x, lo=0, hi=len(a)):等价于a.insert(bisect.bisect(a, x, lo, hi), x)。

insort和bisect区别在于后者返回索引,前者直接操作插入,
arr = [1, 2, 3, 4, 4, 4, 5]
bisect.insort(arr, 6) # 插入数值,若已存在则在所有已存在值的右侧插入
print(arr)
bisect.insort_right(arr, 4) # 插入数值在 所有已存在值的 右侧
print(arr)
bisect.insort_left(arr, 5) # 插入数值在 所有已存在值的 左侧
print(arr)

————————————————
版权声明:本文为CSDN博主「Stephen__W」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/w1301100424/article/details/99200842

import bisect
def inc_max(l):
    dp = [1]*len(l) # 初始化dp,最小递增子序列长度为1
    arr = [l[0]] # 创建数组
    for i in range(1,len(l)): # 从原序列第二个元素开始遍历
        if l[i] > arr[-1]:
            arr.append(l[i])
            dp[i] = len(arr)
        else:
            pos = bisect.bisect_left(arr, l[i]) # 用二分法找到l[i]要插入的位置
            arr[pos] = l[i]
            dp[i] = pos+1#得到最长递增子序列长度
    return dp 

while True:
    try:
        N = int(input())
        s = list(map(int, input().split()))
        left_s = inc_max(s) # 从左至右
        right_s = inc_max(s[::-1])[::-1] # 从右至左
        sum_s = [left_s[i]+right_s[i]-1 for i in range(len(s))] # 相加并减去重复计算
        print(str(N-max(sum_s)))
    except:
        break

HJ26 字符串排序
编写一个程序,将输入字符串中的字符按如下规则排序。
规则 1 :英文字母从 A 到 Z 排列,不区分大小写。
如,输入: Type 输出: epTy

规则 2 :同一个英文字母的大小写同时存在时,按照输入顺序排列。
如,输入: BabA 输出: aABb

规则 3 :非英文字母的其它字符保持原来的位置。
如,输入: By?e 输出: Be?y

while True:#没想出来简单方法,看看大神写的
    try:
        a=input()
        #构造两个列表,一个列表用来放全字母的字符串2,另外一个列表取出来
        char=[] #构造一个列表用来存放字符串
        res=[False]*len(a)#构造一个列表用来记住非字母的位置
        for i,v in enumerate(a):#enumerate用于可遍历的数据对象 i下标,v字符
            if v.isalpha(): #如果全是字母则放入char中
                char.append(v)
            else:
                res[i]=v
        #然后对char进行排序
        char.sort(key=lambda c:c.lower())#按照其小写字母排序
        #重构,在res中的false项中放入char
        for i,v in enumerate(res):
            if not v:#该位置不存在非字母时从字母列表对应位取一个出来
                res[i]=char[0]
                char.pop(0)
        print(''.join(res))       
    except:
        break

HJ27 查找兄弟单词
定义一个单词的“兄弟单词”为:交换该单词字母顺序(注:可以交换任意次),而不添加、删除、修改原有的字母就能生成的单词。
兄弟单词要求和原来的单词不同。例如: ab 和 ba 是兄弟单词。 ab 和 ab 则不是兄弟单词。
现在给定你 n 个单词,另外再给你一个单词 x ,让你寻找 x 的兄弟单词里,按字典序排列后的第 k 个单词是什么?
注意:字典中可能有重复单词。

这个题目很难理解的容易看不懂,首先输入单词数,然后输入这么多单词一大串作为字典,再输入一个单词x和一个整数k,要从输入的一大串中搜索到单词x的兄弟单词并输出数目,然后再打印出其中第k个兄弟单词
字典里面不能有跟单词x一模一样的单词

#是否有简便操作?看大神代码
while True:
    try:
        ss=input().split()
        n=int(ss[0])
        dict=ss[1:n+1]
        s=ss[-2]
        m=int(ss[-1])
        a=[]
        for i in dict:
            if len(i)==len(s) and i!=s and sorted(i)==sorted(s):#sorted(i)==sorted(s)妙啊
                a.append(i)
        print(len(a))
        if a and m<=len(a):
            print(sorted(a)[m-1])
    except:
        break

HJ29 字符串加解密
对输入的字符串进行加解密,并输出。
加密方法为:
当内容是英文字母时则用该英文字母的后一个字母替换,同时字母变换大小写,如字母a时则替换为B;字母Z时则替换为a;
当内容是数字时则把该数字加1,如0替换1,1替换2,9替换0;
其他字符不做变化。
解密方法为加密的逆过程。

def encode(s):
    s_=''
    for i in range(0,len(s)):
        if(s[i].isalpha()):
            k=ord(s[i])
            if(k==90):
                c='a'
            elif(k==122):
                c='A'
            else:    
                c=chr(k+1)
                c=c.swapcase()
            s_+=c
        elif(s[i].isdigit):
            if(s[i]=='9'):
                s_+='0'
            else:
                s_+=str(int(s[i])+1)
        else:
            s_+=(s[i])
    print(s_)
    
def decode(s):
    s_=''
    for i in range(0,len(s)):
        if(s[i].isalpha()):
            k=ord(s[i])
            if(k==65):
                c='z'
            elif(k==97):
                c='Z'
            else:    
                c=chr(k-1)
                c=c.swapcase()
            s_+=(c)
        elif(s[i].isdigit):
            if(s[i]=='0'):
                s_+='9'
            else:
                s_+=str(int(s[i])-1)
        else:
            s_+=(s[i])
    print(s_)                
                
while(1):
    try:
        s1=input()
        s2=input()
        encode(s1)
        decode(s2)
    except:
        break

HJ32 密码截取
Catcher是MCA国的情报员,他工作时发现敌国会用一些对称的密码进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或结束时加入一些无关的字符以防止别国破解。比如进行下列变化 ABBA->12ABBA,ABA->ABAKK,123321->51233214 。因为截获的串太长了,而且存在多种可能的情况(abaaab可看作是aba,或baaab的加密形式),Cathcer的工作量实在是太大了,他只能向电脑高手求助,你能帮Catcher找出最长的有效密码串吗?

#超时版。。。
def huiwen(s,i,j):
    s_part=s[i:j]
    s_part_rev=s_part[::-1]
    if(s_part==s_part_rev):
        #print(s_part,s_part_rev,len(s))
        return len(s_part)
    else:
        return max(huiwen(s,i+1,j),huiwen(s,i,j-1))
s=input()
print(huiwen(s,0,len(s)))

#大神版
# ABA型:只需要从当前字符向两边扩散,比较左右字符是否相等,找出以当前字符为中心的最长回文子串长度
# ABBA型:只需要从当前字符和下一个字符向两边扩散,比较左右字符是否相等,找出以当前字符和下一个字符为中心的最长回文子串长度
# 最后比对两种类型的长度,取自较长的长度
str = input()
n = len(str)
list = []
for i in range(0,n-1):#i:0~2
    for j in range(1,n):#j:1~n-1
        if str[j] == str[i] and str[i+1:j] == str[j-1:i:-1]:
        #后半句解读:i+1~j-1,j-1~i+1方向反过来所以后开是i+1 整体依然是个判回文的操作
        #整句解读:aba abba都是先得到第一个和最后一个字符相同,然后去掉它们的子串为回文串
            list.append(len(str[i:j+1]))
print(max(list))

HJ33 整数与IP地址间的转换
原理:ip地址的每段可以看成是一个0-255的整数,把每段拆分成一个二进制形式组合起来,然后把这个二进制数转变成
一个长整数。
举例:一个ip地址为10.0.3.193
每段数字 相对应的二进制数
10 00001010
0 00000000
3 00000011
193 11000001
组合起来即为:00001010 00000000 00000011 11000001,转换为10进制数就是:167773121,即该IP地址转换后的数字就是它了。

s=input().split('.')
n=''
for i in s:
    s_=str(bin(int(i)))
    s_=s_.replace('0b','')
    if(len(s_)<8):
        s_='0'*(8-len(s_))+s_
        #print(s_)
    n+=s_
#print(n)
print(int(n,2))
s=input()
s=bin(int(s))
s=str(s)
s=s.replace('0b','')
if(len(s)<32):
        s='0'*(32-len(s))+s
#print(s)
l=[]
l.append(str(int(s[0:8],2)))
l.append(str(int(s[8:16],2)))
l.append(str(int(s[16:24],2)))
l.append(str(int(s[24:32],2)))
print(l[0]+'.'+l[1]+'.'+l[2]+'.'+l[3])
#可以再简便的地方是s=bin(i)[2:]替代.replace()函数

HJ36 字符串加密
有一种技巧可以对数据进行加密,它使用一个单词作为它的密匙。下面是它的工作原理:首先,选择一个单词作为密匙,如TRAILBLAZERS。如果单词中包含有重复的字母,只保留第1个,将所得结果作为新字母表开头,并将新建立的字母表中未出现的字母按照正常字母表顺序加入新字母表。如下所示:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
T R A I L B Z E S C D F G H J K M N O P Q U V W X Y (实际需建立小写字母的字母表,此字母表仅为方便演示)
上面其他用字母表中剩余的字母填充完整。在对信息进行加密时,信息中的每个字母被固定于顶上那行,并用下面那行的对应字母一一取代原文的字母(字母字符的大小写状态应该保留)。因此,使用这个密匙, Attack AT DAWN (黎明时攻击)就会被加密为Tpptad TP ITVH。
请实现下述接口,通过指定的密匙和明文得到密文。
数据范围1≤n≤100 ,保证输入的字符串中仅包含小写字母

s=input()
l=[]
for i in range(len(s)):
    if(s[i] not in l):
        l.append(s[i])
for j in range(97,123):
    if(chr(j) not in l):
        l.append(chr(j))
s_ori=input()
s=''
for i in range(len(s_ori)):
    k=ord(s_ori[i])-97
    s+=l[k]
print(s)

HJ38 求小球落地5次后所经历的路程和第5次反弹的高度
假设一个球从任意高度自由落下,每次落地后反跳回原高度的一半; 再落下, 求它在第5次落地时,共经历多少米?第5次反弹多高?
输入起始高度,int型
你可以认为你输出保留六位或以上小数的结果可以通过此题。

#没意识到是等比数列。。。。
h = int(input())
an = h*(1/2 ** 5)			# 等比数列第6项,因为第一次是直接下落,没有上升,所以第五次上升就是等比数列的第六项
sn = (h*(1 - (1/2 ** 5))) / (1 - 1/2)	# 等比数列前6项之和。
print(sn*2 - h)				# 除了第一次是直接下落之外,其它都是先反弹,在下落。因此总路程翻倍-第一次下落的高度即可
print(an)

HJ41 称砝码
现有n种砝码,重量互不相等,分别为 m1,m2,m3…mn ;
每种砝码对应的数量为 x1,x2,x3…xn 。现在要用这些砝码去称物体的重量(放在同一侧),问能称出多少种不同的重量。
注:
称重重量包括 0
对于每组测试数据:
第一行:n — 砝码的种数(范围[1,10])
第二行:m1 m2 m3 … mn — 每种砝码的重量(范围[1,2000])
第三行:x1 x2 x3 … xn — 每种砝码对应的数量(范围[1,10])
输出描述:
利用给定的砝码可以称出的不同的重量数

#没有一个很好的想法,看看大神怎么解的
while True:
    try:
        n = int(input())
        m = input().split(" ")
        x = input().split(" ")
        # mx为所有砝码,比如示例mx为[1, 1, 2]
        mx, l = [], {0}
        for i in range(n):
            mx.extend([int(m[i])] * int(x[i]))
            #extend() 函数用于在列表末尾一次性追加另一个序列中的多个值
        for i in mx:
            # 每次加一块砝码,使用union(并集)得到新去重的组合,如果不使用union则稍微麻烦一点,需要考虑循环中改变set
            l = l.union({i+j for j in l})
        print(len(l))
    except:
        break
#法2
while 1:
    try:
        n = int(input())
        m = map(int, input().split())#重量
        x = map(int, input().split())#数量
        weights = {0}
        for xi, mi in zip(x, m):
            for i in range(xi):
                weights |= set([s+mi for s in weights])#set的操作
        print(len(weights))
    except:
        break

HJ43 迷宫问题
定义一个二维数组 N*M ,如 5 × 5 数组下所示:
int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。
数据范围: 2≤n,m≤10 , 输入的内容只包含 0≤val≤1
输入描述:
输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。
输出描述:
左上角到右下角的最短路径,格式如样例所示。

#DFS搜索的本质就是递归回溯,大神做法如下:
def dfs(i,j):
    dx = [0,0,-1,1]
    dy = [-1,1,0,0]
    if i == m-1 and j == n-1:
        for pos in route:
            print('('+str(pos[0])+','+str(pos[1])+')')
        return
    
    for k in range(4):
        x = i+dx[k]
        y = j+dy[k]
        if x>=0 and x<m and y>=0 and y<n and map1[x][y]==0:
            map1[x][y]=1
            route.append((x,y))
            dfs(x,y)#递归
            map1[x][y]=0#还原回来走下一趟循环
            route.pop()#回溯
    else:
        return
            

while True:
    try:
        m,n = list(map(int,input().split()))
        map1=[]
        for i in range(m):
            s=list(map(int,input().split()))
            map1.append(s)
		# 初始值是(0,0)将其标记为已经访问
        route = [(0,0)]
        map1[0][0]=1
        dfs(0, 0)
        
    except:
        break

HJ45 名字的漂亮度
描述
给出一个字符串,该字符串仅由小写字母组成,定义这个字符串的“漂亮度”是其所有字母“漂亮度”的总和。
每个字母都有一个“漂亮度”,范围在1到26之间。没有任何两个不同字母拥有相同的“漂亮度”。字母忽略大小写。
给出多个字符串,计算每个字符串最大可能的“漂亮度”。
本题含有多组数据。
数据范围:输入的名字长度满足 1≤n≤10000
输入描述:
第一行一个整数N,接下来N行每行一个字符串
输出描述:
每个字符串可能的最大漂亮程度

def calcul(s):
    dic={}
    sum=0
    for i in range(len(s)):
        if(s[i] in dic):
            dic[s[i]]+=1
        else:
            dic[s[i]]=1
    dic=sorted(dic.items(),key=lambda x:x[1],reverse=True)
    k=0
    for j in range(26,0,-1):
        if(k<len(dic)):
            sum+=j*int(dic[k][1])
            k+=1
    
    print(sum)
n=int(input())
for i in range(n):
    s=input()
    calcul(s)

#感觉还是啰嗦,看看大神版
while True:
    try:
        a= int(input())
        s=[]
        for i in range(0, a):
            s.append(input().lower())
        for each in s:
            sum1=0
            c=26
            count=[]
            for i in list(set(each)):
            #set(zhangsan)={'g', 'a', 'n', 'h', 's', 'z'}
                count.append(each.count(i))
                count=sorted(count,reverse=1)
                #也就是说 只需要记录下重复字母的个数从高到低排序,不需要和字母是谁一一对应

            for i in count:
                sum1+=int(i)*c
                c-=1
            print(sum1)
    except:
        break

HJ48 从单向链表中删除指定值的节点
描述
输入一个单向链表和一个节点的值,从单向链表中删除等于该值的节点,删除后如果链表中无节点则返回空指针。
链表的值不能重复。
构造过程,例如输入一行数据为:
6 2 1 2 3 2 5 1 4 5 7 2 2
则第一个参数6表示输入总共6个节点,第二个参数2表示头节点值为2,剩下的2个一组表示第2个节点值后面插入第1个节点值,为以下表示:
1 2 表示为
2->1
链表为2->1

3 2表示为
2->3
链表为2->3->1

5 1表示为
1->5
链表为2->3->1->5

4 5表示为
5->4
链表为2->3->1->5->4

7 2表示为
2->7
链表为2->7->3->1->5->4

最后的链表的顺序为 2 7 3 1 5 4

最后一个参数为2,表示要删掉节点为2的值
删除 结点 2
则结果为 7 3 1 5 4

数据范围:链表长度满足1≤n≤1000 ,节点中的值满足0≤val≤10000

测试用例保证输入合法

输入描述:
输入一行,有以下4个部分:
1 输入链表结点个数
2 输入头结点的值
3 按照格式插入各个结点
4 输入要删除的结点的值
输出描述:
输出一行
输出删除结点后的序列,每个数后都要加空格

#法1:真的构造链表
class ListNode:
    def __init__(self, val):
        self.val = val
        self.next = None
# 根据题意在node链表中插入节点        
def insert(node, val1, val2):
    """
    node:待操作链表
    val1:第一个节点值
    val2:第二个节点值
    return:操作后的链表node
    """
    gummy = node
    while gummy:
        next = gummy.next
        if gummy.val == val2:
            gummy.next = ListNode(val1)
            gummy.next.next = next
            break
        else:
            gummy = gummy.next
    return node
        
while True:
    try:
        lis = list(map(int, input().split()))
        # 插入节点
        head = ListNode(lis[1])
        new_lis = lis[2:len(lis)-1]
        result = []
        left = 0
        right = 1
        while right < len(new_lis):
            head = insert(head, new_lis[left], new_lis[right])
            left += 2
            right += 2
        dummy = head 
        # 删除节点
        while dummy:
            if dummy.next.val == lis[-1]:
                dummy.next = dummy.next.next
                break
            else:
                dummy = dummy.next
        # 打印节点值
        while head:
            print(head.val,end=" ")
            head= head.next
    except EOFError:
        break
    
#法2:list模拟
s=input().split()
n=s[0]
l=[s[1]]
for i in range(2,len(s)-2,2):
    if(s[i+1] not in l):
        l.append(s[i+1])
    else:
        k=l.index(s[i+1])
        l.insert(k+1,s[i])
l.remove(s[len(s)-1])
for i in l:
    print(i,end=' ')

HJ50 四则运算
输入一个表达式(用字符串表示),求这个表达式的值。
保证字符串中的有效字符包括[‘0’-‘9’],‘+’,‘-’, ‘*’,‘/’ ,‘(’, ‘)’,‘[’, ‘]’,‘{’ ,‘}’。且表达式一定合法。

print(eval(input().replace('{','(').replace('}',')').replace('[','(').replace(']',')')))#把表达式里中括号大括号全换成小括号即可

HJ52 计算字符串的编辑距离
Levenshtein 距离,又称编辑距离,指的是两个字符串之间,由一个转换成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。编辑距离的算法是首先由俄国科学家 Levenshtein 提出的,故又叫 Levenshtein Distance 。
例如:
字符串A: abcdefg
字符串B: abcdef
通过增加或是删掉字符 ”g” 的方式达到目的。这两种方案都需要一次操作。把这个操作所需要的次数定义为两个字符串的距离。
要求:
给定任意两个字符串,写出一个算法计算它们的编辑距离。
数据范围:给定的字符串长度满足 1≤len(str)≤1000

levenshtein距离

需要运用动态规划去解决该类问题。
传递公式:
lev[i][j]用来表示字符串a的[1…i]和字符串b[1…j]的levenshtein距离;
插入和删除操作互为逆过程:a删除指定字符变b等同于b插入指定字符变a;
如果a[i] == b[j],则说明a[i]和b[j]分别加入a,b之后不会影响levenshtein距离,lev[i][j] 直接转换为考虑 lev[i-1][j-1] + 0;即A[i-1] == B[j-1]时,最后一个元素不用动,只用考虑A[0,…i-2]编辑为B[0,…j-2]需要的代价,dp[i][j] = dp[i-1][j-1]
如果a[i] != b[j],则需要考虑3种情况的可能:
a中插入字符,即lev[i][j] = lev[i-1][j] + 1;
b中插入字符,即lev[i][j] = lev[i][j-1] + 1;
a[i]替换成b[j],lev[i][j] = lev[i-1][j-1] + 1;
取这4种情况的最小值。
这种解法(如下)一定存在大量重叠子问题。比如能过替换得到的结果也可以通过删除后插入完成,这就是一条重复路径,如果发现了一定重复问题,那么一定会有千千万万个重复问题,就像斐波那契数列一样。而重叠子问题是可以通过备忘录解决的

int dp(i,j)
{
    if i==-1
        return j+1;
    if j==-1
        return i+1;
    if(s1[i]==s[j])
        return dp[i-1][j-1];
    else
        return min(
        dp(i,j-1)+1;//插入
        dp(i-1,j)+1;//删除
        dp(i-1,j-1)+1;//替换
    )
}
#重叠子问题是可以通过备忘录解决的,如下
memo=dict();
int dp(i,j)
{
    if((i,j) in memo)
        return memo[(i,j)];
    if i==-1
        return j+1;
    if j==-1
        return i+1;
    if(s1[i]==s[j])
        return dp[i-1][j-1];
    else
        return min(
        dp(i,j-1)+1;//插入
        dp(i-1,j)+1;//删除
        dp(i-1,j-1)+1;//替换
    )
}
#本题真正能通过的代码:
 def levenDis(s1, s2):
    M, N = len(s1), len(s2)
    # dp[i][j]: 字符s1的前i个字符是由字符s2的前j字符,通过dp[i][j]变换得到的
    dp = [[0 for _ in range(N + 1)] for _ in range(M + 1)]
    dp[0][0] = 0
    
    for i in range(1, M+1):
        dp[i][0] = i     # 增加
        
    for j in range(1, N+1):
        dp[0][j] = j     # 删除
        
    for i in range(1, M+1):
        for j in range(1, N+1):
            if s1[i-1] == s2[j-1]:
                dp[i][j] = dp[i-1][j-1]
            else:
                dp[i][j] = min(dp[i-1][j] + 1, # 删除
                         dp[i][j-1] + 1,  # 增加
                         dp[i-1][j-1] + 1)  # 替换
    print(dp[M][N])
                
while True:
    try:
        s1, s2 = input(), input()
        levenDis(s1, s2)
        
    except:
        break

HJ63 DNA序列
描述
一个 DNA 序列由 A/C/G/T 四个字母的排列组合组成。 G 和 C 的比例(定义为 GC-Ratio )是序列中 G 和 C 两个字母的总的出现次数除以总的字母数目(也就是序列长度)。在基因工程中,这个比例非常重要。因为高的 GC-Ratio 可能是基因的起始点。
给定一个很长的 DNA 序列,以及限定的子串长度 N ,请帮助研究人员在给出的 DNA 序列中从左往右找出 GC-Ratio 最高且长度为 N 的第一个子串。
DNA序列为 ACGT 的子串有: ACG , CG , CGT 等等,但是没有 AGT , CT 等等
数据范围:字符串长度满足 1≤n≤1000 ,输入的字符串只包含 A/C/G/T 字母
输入描述:
输入一个string型基因序列,和int型子串的长度
输出描述:
找出GC比例最高的子串,如果有多个则输出第一个的子串

s=input()
n=int(input())
maxcg=0
substr=''
for i in range(len(s)):
    if(i+n<=len(s)):
        cg=s[i:i+n].count('C')+s[i:i+n].count('G')
    else:
        break
    if(cg>maxcg):
        maxcg=cg
        substr=s[i:i+n]
print(substr)
#CCCAAGTCTTCCAATCGTGCCCCCCAATTGAGTCTCGCTCCCCAGGTGAGATACATCAGAAGC
#63
#CCCAAGTCTTCCAATCGTGCCCCCCAATTGAGTCTCGCTCCCCAGGTGAGATACATCAGAAGC

HJ64 MP3光标位置
MP3 Player因为屏幕较小,显示歌曲列表的时候每屏只能显示几首歌曲,用户要通过上下键才能浏览所有的歌曲。为了简化处理,假设每屏只能显示4首歌曲,光标初始的位置为第1首歌。
现在要实现通过上下键控制光标移动来浏览歌曲列表,控制逻辑如下:
1)歌曲总数<=4的时候,不需要翻页,只是挪动光标位置。
光标在第一首歌曲上时,按Up键光标挪到最后一首歌曲;光标在最后一首歌曲时,按Down键光标挪到第一首歌曲。其他情况下用户按Up键,光标挪到上一首歌曲;用户按Down键,光标挪到下一首歌曲。
2)歌曲总数大于4的时候(以一共有10首歌为例):
特殊翻页:屏幕显示的是第一页(即显示第1 – 4首)时,光标在第一首歌曲上,用户按Up键后,屏幕要显示最后一页(即显示第7-10首歌),同时光标放到最后一首歌上。同样的,屏幕显示最后一页时,光标在最后一首歌曲上,用户按Down键,屏幕要显示第一页,光标挪到第一首歌上。
一般翻页:屏幕显示的不是第一页时,光标在当前屏幕显示的第一首歌曲时,用户按Up键后,屏幕从当前歌曲的上一首开始显示,光标也挪到上一首歌曲。光标当前屏幕的最后一首歌时的Down键处理也类似。
其他情况,不用翻页,只是挪动光标就行。
输入描述:
输入说明:
1 输入歌曲数量
2 输入命令 U或者D
输出描述:
输出说明
1 输出当前列表
2 输出当前选中歌曲
坑:1.不能将u/d看作完全独立互不影响的逆操作(见下方注释的错误处理)
2.滑动窗口是否变换取决于当前光标和滑动窗口边界的关系,当光标等于窗口上边界且还要往上时需要把窗口整体往上挪,当光标处于边界之间是不管上还是下窗口边界都不变,当光标等于窗口下边界且还要往下时需要把窗口整体向下挪。

#import math
music_num=int(input())
ins=list(input())
'''错误处理,ud不是完全独立的逆操作
while(ins.count('U') and ins.count('D')):
    ins.remove('U')
    ins.remove('D')
'''
#print(ins)
temp=1
cur1=1#滑动窗口,谁小先输出谁 差3
cur2=4
for j in ins:
    if(j=='U'):
        if(temp==1):
            temp=music_num
            cur1=music_num-3
            cur2=cur1+3
        elif(cur1==temp):
            temp-=1
            cur1=temp
            cur2=cur1+3
        else:
            temp-=1
    elif(j=='D'):
        if(temp==music_num):
            temp=1
            cur1=1
            cur2=4
        elif(temp>=4 and abs(temp-cur1)>=3):
            temp+=1
            cur1+=1
            cur2=cur1+3
        else:
            temp+=1


    #print(temp-3,temp-2,temp-1,temp)
if(music_num>=4):
    print(cur1,cur1+1,cur1+2,cur1+3)
else:
    i=1
    while(i<=cur2):
        if(i!=cur2):
            print(i,end=' ')
        else:
            print(i)
        i+=1

print(temp)
#83
#UUDUDDDDUDUUDDDDUDD
#3 4 5 6 
#6
#107
#UDDUUDUDDUUDDDDDDUUDUDDUUUU
#2 3 4 5 
#2

HJ65 查找两个字符串a,b中的最长公共子串
描述
查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
注:子串的定义:将一个字符串删去前缀和后缀(也可以不删)形成的字符串。请和“子序列”的概念分开!
数据范围:字符串长度1≤length≤300
输入描述:
输入两个字符串
输出描述:
返回重复出现的字符

最长公共子串

#没做出来,反思!!!
while True:
    try:
        a, b = input(), input() # a保存短,b保存长
        if len(a) > len(b):
            a, b = b, a#交换
        res = ''
        for i in range(0, len(a)):
            for j in range(i+1, len(a)):
                if a[i:j+1] in b and j+1-i > len(res):#a[i:j+1] in b表示查找是否为子串
                    res = a[i:j+1]
        print(res)
    except:
        break

HJ66 配置文件恢复
有6条配置命令,它们执行的结果分别是:
命 令 执 行
reset reset what
reset board board fault
board add where to add
board delete no board at all
reboot backplane impossible
backplane abort install first
he he unknown command
注意:he he不是命令。
为了简化输入,方便用户,以“最短唯一匹配原则”匹配(注:需从首字母开始进行匹配):
1、若只输入一字串,则只匹配一个关键字的命令行。例如输入:r,根据该规则,匹配命令reset,执行结果为:reset what;输入:res,根据该规则,匹配命令reset,执行结果为:reset what;
2、若只输入一字串,但匹配命令有两个关键字,则匹配失败。例如输入:reb,可以找到命令reboot backpalne,但是该命令有两个关键词,所有匹配失败,执行结果为:unknown command
3、若输入两字串,则先匹配第一关键字,如果有匹配,继续匹配第二关键字,如果仍不唯一,匹配失败。
例如输入:r b,找到匹配命令reset board 和 reboot backplane,执行结果为:unknown command。
例如输入:b a,无法确定是命令board add还是backplane abort,匹配失败。
4、若输入两字串,则先匹配第一关键字,如果有匹配,继续匹配第二关键字,如果唯一,匹配成功。例如输入:bo a,确定是命令board add,匹配成功。
5、若输入两字串,第一关键字匹配成功,则匹配第二关键字,若无匹配,失败。例如输入:b addr,无法匹配到相应的命令,所以执行结果为:unknow command。
6、若匹配失败,打印“unknown command”
注意:有多组输入。
数据范围:数据组数:1≤t≤800 ,字符串长度1≤s≤20
输入描述:
多行字符串,每行字符串一条命令
输出描述:
执行结果,每条命令输出一行

双层切片

没看懂这题啥意思,找了个题解,关键点:
1.先判断输入字符串的长度,长度为1时,只匹配关键词为1的字符串,比如输入r只能匹配reset,同理长度为2的只能匹配关键词长度为2的字符串,比如输入r b,只能匹配reset board和reboot backplane。
2.如果匹配出的结果不唯一,也就是匹配到两个,则匹配不成功。比如输入r b,匹配reset board和reboot backplane,用计数器可以解决,此时输出 unknown command

#看了大神写的切片思想佩服了,不用字典免去了双层循环的做法,偷来粘在这里供大家欣赏。
#精华之处:key[list_index][:len(m[0])]
while True:
    try:
        m=input().strip().split()
        key=["reset","reset board","board add","board delete","reboot backplane","backplane abort"]
        value=["reset what","board fault","where to add","no board at all","impossible","install first"]
        #不建字典,用列表的方式避免了双层循环,如果实在要用dic字典,直接用dict(zip(list1,list2))合成字典都行.
        if len(m)<1 or len(m)>2:   #判断当输入为小于1个或者输入大于2个字符串时,不符合命令,就报未知命令
            print("unknown command")
        elif len(m)==1:   #当输入一个字符串
            if m[0]==key[0][:len(m[0])]:  #这里才是解决这个题的最佳思想,利用切片的思想来匹配
                print(value[0])
            else:
                print("unknown command")
        else:
            index=[]
            for i in range(1,len(key)): #这里把所有原始命令遍历,如果这里写成(len(key)+1),也就是1..6,那么下面的key[i]要改成k[i-1]才符合逻辑
                a=key[i].split() #将具体的一个KEY分割成两部分
                if m[0]==a[0][:len(m[0])] and m[1]==a[1][:len(m[1])]:  #然后去匹配被分割的key,这里不可能有reset这种单独的,因为上面条件已经限制了。
                    index.append(i)  #符合条件就把这个位置入列表
            if len(index)!=1:#妙啊
                print("unknown command")
            else:
                print(value[index[0]]) #输出对应的value值
    except:
        break

HJ67 24点游戏算法
描述
给出4个1-10的数字,通过加减乘除运算,得到数字为24就算胜利,除法指实数除法运算,运算符仅允许出现在两个数字之间,本题对数字选取顺序无要求,但每个数字仅允许使用一次,且需考虑括号运算
此题允许数字重复,如3 3 4 4为合法输入,此输入一共有两个3,但是每个数字只允许使用一次,则运算过程中两个3都被选取并进行对应的计算操作。
输入描述:
读入4个[1,10]的整数,数字允许重复,测试用例保证无异常数字。
输出描述:
对于每组案例,输出一行表示能否得到24点,能输出true,不能输出false

递归解决暴力枚举的计算问题

#感觉暴力的话太暴力了,看看大神怎么做的
def helper(arr,item):#先写一个利用递归+枚举解决算24的程序
    if item<1:#剩余的最后一个值范围是[1,10],这里判断若item不在这个范围内,则最后生的那个数肯定与其不等,不成立
        return False
    if  len(arr)==1:#递归终点,当数组arr只剩一个数的时候,判断是否等于item
        return arr[0]==item
    else:#如果arr不是只剩一个数,就调用函数本身(直到只剩一个为止返回真假) 
        for i in range(len(arr)):
            m=arr[0:i]+arr[i+1:]#取出除n以外的其他数,规律是随着i变化在arr里挨个取n
            n=arr[i]
            if helper(m,item+n) or helper(m, item-n) or helper(m, item*n) or helper(m, item/n):#将n与结果值先进行运算,只要有一个成立则成立
                return True
        return False

while True:
    try:
        if helper(list(map(int,input().split())), 24):
            print('true')
        else:
            print('false')
    except:
        break

HJ69 矩阵乘法
输入:第一行包含一个正整数x,代表第一个矩阵的行数
第二行包含一个正整数y,代表第一个矩阵的列数和第二个矩阵的行数
第三行包含一个正整数z,代表第二个矩阵的列数
之后x行,每行y个整数,代表第一个矩阵的值
之后y行,每行z个整数,代表第二个矩阵的值

利用list制作矩阵

while True:
    try:
        x = int(input())
        y = int(input())
        z = int(input())
        A = []
        B = []
        for i in range(x):
            A.append(list(map(int,input().split()))) 
        for j in range(y):
            B.append(list(map(int,input().split())))
        #输入录入后,开始计算,先初始化一个二维数组,初始值为0
        R=[[0 for k in range(z)] for i in range(x)]
        for i in range(x):#矩阵乘积的行数
            for k in range(z):#矩阵乘积的列数
                for j in range(y): #计算每个输出单元格的数据,A行与B列的乘积,长度为y
                    R[i][k] += A[i][j] * B[j][k]
        #按行输出
        for i in range(x):
            for k in range(z):
                print(R[i][k], end = ' ')
            print('')
    except:
        break

HJ70 矩阵乘法计算量估算
描述
矩阵乘法的运算量与矩阵乘法的顺序强相关。
例如:
A是一个50×10的矩阵,B是10×20的矩阵,C是20×5的矩阵
计算ABC有两种顺序:((AB)C)或者(A(BC)),前者需要计算15000次乘法,后者只需要3500次。
编写程序计算不同的计算顺序需要进行的乘法次数。保证给出的字符串表示的计算顺序唯一。
输入描述:
输入多行,先输入要计算乘法的矩阵个数n,每个矩阵的行数,列数,总共2n的数,最后输入要计算的法则
计算的法则为一个字符串,仅由左右括号和大写字母(‘A’~‘Z’)组成,保证括号是匹配的且输入合法!
输出描述:
输出需要进行的乘法次数

乘法计算量计算

A(m*n)乘B(n*p)的乘法次数为m*n*p
对rule进行逐个字符的遍历,并进行相应处理:
字符是左括号,入栈
字符是右括号,出栈两个,并计算,计算完将新矩阵入栈
字符是非括号,入栈
出栈处理:
如果只有一个矩阵,无法进行矩阵乘法,程序结束。
如果有多个矩阵,出栈最后两个。注:先出栈的为第二个矩阵,后出栈的为第一个矩阵
计算单次矩阵乘法运算的乘法次数,得到运算后的新矩阵
while True:
try:
    n = int(input())
    matrix_list = []
    for i in range(n):
        matrix_list.append([int(i) for i in input().split()])
    rule = input()
    
    temp = []
    times = 0
    for i in rule:
        if i.isalpha():
            temp.append(i)
        elif i == ')':
            x = temp.pop()#第二个矩阵
            y = temp.pop()#第一个矩阵
            times += matrix_list[ord(y)-65][0] * matrix_list[ord(y)-65][1] * matrix_list[ord(x)-65][1]
            matrix_list[ord(y)-65] = (matrix_list[ord(y)-65][0], matrix_list[ord(x)-65][1])#运算完的新矩阵
            temp.append(y)
    print(times)
    
except:
    break

HJ71 字符串通配符
要求:
实现如下2个通配符:
:匹配0个或以上的字符(注:能被和?匹配的字符仅由英文字母和数字0到9组成,下同)
?:匹配1个字符
注意:匹配时不区分大小写。
输入描述:
先输入一个带有通配符的字符串,再输入一个需要匹配的字符串
输出描述:
返回不区分大小写的匹配结果,匹配成功输出true,匹配失败输出false

大神总结下来的经验:
匹配逻辑
从右向左识别符号,通配符p可能有三种类型:
1.普通字符
2.?
3.*
前两种情况可以合并为检查字符串s(n-2) 与通配符 p(m-2) 是否匹配。
第三种分为两个情形:
(1)无视* 字符串s(n-1) 与通配符 p(m-2) 是否匹配。
(2)考虑* 字符串s(n-2) 与通配符 p(m-1) 是否匹配。

边界条件
需要分别考虑字符串为空、通配符为空的情形。
归纳如下:
1.字符串s='' 通配符 p='' 匹配结果为 True
2.字符串s!='' 通配符 p='' 匹配结果为 False
3.字符串s='' 通配符 p!='' 继续分两种情况:
(1) p里全是* 匹配结果为 True
(2) p里不全是* 匹配结果为 False
4.字符串与通配符均不为'',则需要开展比对,按三种开头梳理的三种类型分别设计检查判断

def fun(str1, str2):
    if str1 == '' and str2 == '':
        return True
    elif str1 == '' and str2 != '':
        return False
    elif str1 != '' and str2 == '':
        if str1.replace('*', '') == '':
            return True
        else:
            return False
    else:
        m, n = len(str1), len(str2)
        if str1[m-1] == str2[n-1] or (str1[m-1] == '?' and str2.isalnum()):
            return fun(str1[:m-1], str2[:n-1])
        elif str1[m-1] == '*':
            return fun(str1[:m-1], str2) or fun(str1, str2[:n-1])
        else:
            return False
while True:
    try:
        str1, str2 = input().lower(), input().lower()
        if fun(str1, str2):
            print('true')
        else:
            print('false')

    except:
        break

HJ74 参数解析

s=input()
l=[]
temp=''
i=0
while(i<len(s)):
    if(s[i]=='"'):
        i+=1
        while(s[i]!='"'):
            temp+=s[i]
            i+=1
            if(i==len(s)):
                break
        i+=1
        if(temp!=''):
            l.append(temp)
        temp=''
    elif(s[i]==' '):
        i+=1
        while(s[i]!=' ' and s[i]!='"'):
            temp+=s[i]
            i+=1
            if(i==len(s)):
                break
        if(temp!=''):
            l.append(temp)
        temp=''
    else:
        while(s[i]!=' '):
            temp+=s[i]
            i+=1
            if(i==len(s)):
                break
        if(temp!=''):
            l.append(temp)
        temp=''
print(len(l))
for i in l:
    print(i)
#大神版
while True:
    try:
        str1=str(input())
        str1=str1.replace(' ','\n')#便于空格直接换行 很妙
        e = ''
        flag = False
        for i in str1:
            if i == '"':  # 经过一次引号则拨动一次开关
                flag = not flag#取反妙啊
            elif flag == True and i == '\n':
                e += ' '
            else:
                e += i
        b = e.count('\n') + 1#计数也妙
        print(b)
        print(e)
    except:
        break

HJ75 公共子串计算
给定两个只包含小写字母的字符串,计算两个字符串的最大公共子串的长度。
注:子串的定义指一个字符串删掉其部分前缀和后缀(也可以不删)后形成的字符串。

#动态规划还是没掌握 但先以暴力做保底
def solution(s1, s2):
    mxlen = 0
    if len(s1) > len(s2):
        s1, s2 = s2, s1            # s1为较短的字符串
    for i in range(len(s1)):
        for j in range(i, len(s1)):
            if s1[i:j+1] in s2 and j + 1 - i > mxlen:    # 从s1中截取所有的子串在s2中进行匹配,并更新最大值
                mxlen = j + 1 - i
    return mxlen

while True:
    try:
        s1 = input()
        s2 = input()
        print(solution(s1,s2))
    except:
        break;
#----华丽分割线
#定义dp[i][j]的含义为在s1,s2中分别以s1[i-1],s2[j-1]为结尾的两个公共子串的长度。当dp[i][j]=0时说明s1[i-1] != s2[j-1]
#遍历两个字符串,指针分别为i和j,当出现s1[i] == s2[j]的时候,则说明需要更新dp[i+1][j+1] = 1 + dp[i][j]
#根据max更新记录的最大值
def solution(s1, s2):
    mxlen = 0
    dp = [[0 for i in range(len(s2)+1)] for j in range(len(s1)+1)]    # 动态规划数组
    for i in range(len(s1)):
        for j in range(len(s2)):                # 想要找到两个字符串中相同的字母,然后看看以这公共字母结尾的子串是否能进行长度拓展
            if s1[i] == s2[j]:
                dp[i+1][j+1] = dp[i][j] + 1     # 更新最长子串的值
                if dp[i+1][j+1] > mxlen:
                    mxlen = dp[i+1][j+1]
    return mxlen

while True:
    try:
        s1 = input()
        s2 = input()
        print(solution(s1,s2))
    except:
        break;

HJ77 火车进站
给定一个正整数N代表火车数量,0 要求输出所有火车出站的方案,以字典序排序输出。

#没思路
def func():
    while True:
        try:
            n = int(input())
            trains = input().strip().split(' ')#总体的先后顺序,后者若入栈未出则前者不能出,前者未进站后者不可进站
              
            res = []
            def rec_trains(cur_idx, in_trains, out_trains):#当前下标,站内车辆,出战车辆
                # 如果原始火车列表的最后一个元素已经进站,此时只能一股脑全出站,将入站列表中的火车倒序加入出站火车中
                if trains[-1] in in_trains:
                    res.append(' '.join(out_trains + in_trains[::-1])); 
                    print(*in_trains[::-1],'出站');print('出站顺序:',res[-1]) 
                    #return
                # 如果进站列表为空,此时只能进站,进站列表加上当前火车,出站列表不变
                elif in_trains == []:
                    print(trains[cur_idx],'进站');
                    rec_trains(cur_idx + 1, in_trains + [trains[cur_idx]], out_trains)
                # 否则,就既有可能进站也有可能出站
                else:
                    # 出站,当前火车索引不变,进站火车列表减去最后一个元素,出站列表加上进站列表刚刚出站的火车
                    print('选A:', in_trains[-1],'出站');rec_trains(cur_idx, in_trains[:-1], out_trains + [in_trains[-1]]) 
                    # 进站,当前火车索引加1,进站列表加上当前火车,出站列表不变
                    print('选B:',trains[cur_idx],'进站');rec_trains(cur_idx + 1, in_trains + [trains[cur_idx]], out_trains)
                    ## 递归“遍历”本质:利用def下if条件句特点;如果有两个选项会一直循环至验证所有可能解
                    
            rec_trains(0, [], [])
            res.sort()
            #print('\n'.join(res))
        except:
            break
if __name__ == '__main__':
    func()
#简易版 有好几种可能情况就都列出来递归
res = []
def dfs(wait, stack, out):
    if not wait and not stack:#wait stack均为空
        res.append(' '.join(map(str, out)))#直接得答案
    if wait: # 入栈
        dfs(wait[1:], stack + [wait[0]], out)#第一个必须先入栈
    if stack: # 出栈
        dfs(wait, stack[:-1], out + [stack[-1]])#如果站里有车就可以选择出站一辆

while True:
    try:
        n, nums = int(input()), list(map(int, input().split()))
        dfs(nums, [], [])
        for i in sorted(res):
            print(i)
    except:
        break

HJ92 在字符串中找出连续最长的数字串
输入一个字符串,返回其最长的数字子串,以及其长度。若有多个最长的数字子串,则将它们全部输出(按原字符串的相对位置)
本题含有多组样例输入。

while(1):
    try:
        max=0
        max_s=[]
        temp_s=''
        temp=0
        s=input()
        i=0
        while(i<len(s)):
            if(s[i].isdigit()):
                while(s[i].isdigit() ):
                    temp+=1
                    temp_s+=s[i]
                    i+=1
                    if(i==len(s)):
                        break
                if(temp>max):
                    max=temp
                    max_s=[]
                    max_s.append(temp_s)
                elif(temp==max):
                    max_s.append(temp_s)
            temp=0  
            temp_s=''
            i+=1
        for i in max_s:
            print(i,end='')
        print(','+str(max))
                
    except:
        break

HJ90 合法IP
IPV4地址可以用一个32位无符号整数来表示,一般用点分方式来显示,点将IP地址分成4个部分,每个部分为8位,表示成一个无符号整数(因此正号不需要出现),如10.137.17.1,是我们非常熟悉的IP地址,一个IP地址串中没有空格出现(因为要表示成一个32数字)。
现在需要你用程序来判断IP是否合法。

踩坑:都是先以.分割后
1)不为数字要报错
2)数字前面有0且不为0的报错
3)分割后长度不为4报错
4)数字大于255报错
s=input().split('.')
res='YES'
for i in s:
    if(i.isdigit()!=1):
        res='NO'
        break
    elif(int(i)>255):
        res='NO'
        break
    if(str(i[0])=='0' and len(i)>1):
        res='NO'
        break
if(len(s)!=4):
    res='NO'
print(res)

HJ82 将真分数分解为埃及分数
分子为1的分数称为埃及分数。现输入一个真分数(分子比分母小的分数,叫做真分数),请将该分数分解为埃及分数。如:8/11 = 1/2+1/5+1/55+1/110。
注:真分数指分子小于分母的分数,分子和分母有可能gcd不为1!
如有多个解,请输出任意一个。

#解题思路1:
将真分数(a/b)拆分成a*(1/b),也就是a个1/b,然后我们从大到小依次找出a中能被b整除的数.
比如: 5/8 这个真分数首先我们看,5不能被8整除,但是4可以,那从5中把4分离出来,变成1+4,剩余的1不能拆分,那埃及分数就是1/8+1/2
再比如:7/8这个真分数,首先我们看,7不能被8整除,6不能被8整除,5不能被8整除,4可以整除,分子分离出4,还剩3,我们看3不能整除,2能整除,分离出2,还剩1, 埃及分数:1/8+1/4+1/2
#解题思路2:z/m=z个1/m相加

HJ103 Redraiment的走法
Redraiment是走梅花桩的高手。Redraiment可以选择任意一个起点,从前到后,但只能从低处往高处的桩子走。他希望走的步数最多,你能替Redraiment研究他最多走的步数吗?
动态规划,即考最长连续递增序列或最长连续子序列

#数组 dp 中存储着对应 nums 位置的桩最大次数,所以创建的时候默认为 1,因为当前桩本身就是一步。
#重难点:i
while True:
    try:
        n, nums = int(input()), list(map(int, input().split()))
        dp = [1] * n#dp根据实际比对的是自己还是对方来做一维/二维矩阵
        for i in range(n):
            for j in range(i):
                if nums[j] < nums[i]:
                    dp[i] = max(dp[i], dp[j] + 1)
        print(max(dp))
    except:
        break

补充排列组合(https://blog.csdn.net/weixin_52693168/article/details/123165114)

排列组合

#方法1:
itertools模块中的permutations方法:permutations(iterable[, r]) --> permutations object
输入两个参数分别为:可迭代对象,从可迭代对象中取出几个值来计算其排列
import itertools
for (x1, x2), (y1, y2), (z1, z2) in itertools.combinations(points, 3):
    print((x1, x2), (y1, y2), (z1, z2))
后面带with replace....的函数是可重复的排列/组合
#方法2:
#全排列 for循环实现
num_list = [1,2,3]
result = []
for i in num_list:
      for j in num_list:
            for k in num_list:
                  if len(set((i,j,k))) == 3:#去重后长度仍为3的话说明i,j,k的值都不相同
                         result.append(list((i,j,k)))
print(result)
#方法3:
# (递归实现)
def Perm(arrs): #全排列
    # 若输入 [1,2,3],则先取出1,将剩余的 [2,3]全排列得到 [[2,3],[3,2]],
    #               再将 1加到全排列 [[2,3],[3,2]]上变成 [[1,2,3],[1,3,2]]
    # 同理,取出2或者3时,得到的分别是 [[2,1,3],[2,3,1]]和 [[3,1,2],[3,2,1]]
    if len(arrs)==1:
        return [arrs]
    result = []  # 最终的结果(即全排列的各种情况)
    for i in range(len(arrs)):  
        rest_arrs = arrs[:i]+arrs[i+1:]  # 取出arrs中的第 i个元素后剩余的元素
        rest_lists = Perm(rest_arrs)   # 剩余的元素完成全排列
        lists = []
        for term in rest_lists:
            lists.append(arrs[i:i+1]+term)  # 将取出的第 i个元素加到剩余全排列的前面
        result += lists
    return result
    
#不是全排列,是k个元素的排列
# (递归实现)
def Perm_k(arrs, k):
    # 若输入 [1,2,3],则先取出1这个元素,将剩余的 [2,3]中取出另一个元素得到 [[1,2],[1,3]]
    # 同理,取出2或者3时,得到的分别是 [[2,1],[2,3]]和 [[3,1],[3,2]]
    if len(arrs)==1:
        return [arrs]
    if k==1:
        return list(map(lambda s:[s], arrs))  #  当 k 为 1 时,每(单)个元素都可以被选取
    result = []  # 最终的结果(即全排列的各种情况)
    for i in range(len(arrs)):  
        rest_arrs = arrs[:i]+arrs[i+1:]  # 取出arrs中的第 i个元素后剩余的元素
        rest_lists = Perm_k(rest_arrs, k-1)     # 剩余的元素选取 k-1元素
        lists = []
        for term in rest_lists:
            lists.append(arrs[i:i+1]+term)  # 将取出的第 i个元素加到剩余全排列的前面
        result += lists
    return result
    
#组合的直接迭代
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
# @param n int整型 
# @param k int整型 
# @return int整型二维数组
#
class Solution:#1~n中取k个
    def combine(self , n: int, k: int) -> List[List[int]]:
        # write code here
        res = []
        def dfs(sub, s):
            nonlocal res
            if len(sub) == k:
                res.append(list(sub))
                return
            for i in range(s, n + 1):
                dfs(sub + [i], i + 1)
        dfs([], 1)
        return res

#之前是直接迭代,也可以搜索迭代
def Perm(arrs, d, k, used, result):#used标记数组
# d 表示搜索深度,k 是设定的最大深度,即 P(n, k)中需要选取的个数
    if d == k:
        print(result)
    for i in range(len(arrs)):
        if used[i]:
            continue
        used[i] = True
        result.append(arrs[i])
        Perm(arrs, d+1, k, used, result)
        result.pop()
        used[i] = False
arrs = [1, 2, 3, 4]
Perm(arrs, 0, 2, [False]*4, [])
#组合
def Comb(arrs, d, k, s, result):#s是当前起始下标
# d 表示搜索深度,k 是设定的最大深度,即 C(n, k)中需要选取的个数
    if d == k:
        print(result)
    for i in range(s, len(arrs)):
        result.append(arrs[i])
        Comb(arrs, d+1, k, i+1, result) 
        result.pop()
        
arrs = [1, 2, 3, 4]
Comb(arrs, 0, 3, 0, [])

补充两道考过的华为机试题

机试题第一道是输出长度为n的字符串的所有组合,输入是字符串s和长度n,然后输出。
相似题目:
假设字符串中的所有字符不重复,如何输出字符串的所有组合,例如,输入字符串为“abc”,则输出a、b、c、ab、ac、bc、abc,共7种组合。如果字符串中有n个字符,根据排列组合的性质,此时一共需要输出2^n-1种组合。https://www.nowcoder.com/practice/837f4d04f5cb4f26a8215b2b95cc76a5?tpId=182&tqId=34795&ru=/exam/oj
别的都好写,最难的在如何输出。这里巧妙用.join()方法

import itertools
s=input()
l=set()
for i in range(0,len(s)):
    for j in range(0,len(s)):
        l.add(s[j:j+i+1])
print(' '.join(sorted(list(l),key=lambda x:(len(x),x))))

机试题第2道是找终点(其变形题目,leecode跳跃游戏,变形后就属于动态规划了)
给定一个正整数数组,最大为100个成员,从第一个成员开始,走到数组最后一个成员最少的步骤数。第一步必须从第一元素开始,1<=步长 样例输入
7 5 9 4 2 6 8 3 5 4 3 9
样例输出
2
(第一步:第一个可选步长选择2,第一个成员7走2步到成员9,第二步,第2个成员为9,经过9个成员到最后)
这个博主的解析很妙,https://blog.csdn.net/qinglingLS/article/details/123765889

def read_data():
    return [int(index) for index in input().split()]
nums = read_data()
for i in range(1, len(nums) // 2):#第一步
    sum = i
    count = 1#当前路线的步数
    res = 100#最终取最小的步数
    length = len(nums)
    while sum < length - 1:#第一步是一开始已经从第一个走到第1+i个
        sum += nums[sum]
        count = count + 1
    if sum == length - 1:
        res = min(count, res)
print(res if res != 100 else -1)

准备华为机试题注意要把之前能够找到的原题都找到做一遍!

动态规划专栏

若上面这道题感觉难的就得要先从最基本的相似题目来看,(动态规划专栏 https://www.nowcoder.com/exam/oj?tab=算法篇&topicId=230),动态规划专项先做前25个

dp1.2全是斐波那契数列的for循环用法:略

dp3跳台阶扩展问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶(n为正整数)总共有多少种跳法。
f(n)=f(n-1)+f(n-2)+…+f(2)+f(1) (i)
f(n-1)=f(n-2)+…+f(1) (ii)
(i)&(ii)式得到f(n)=2f(n-1)
可以发现是等比数列,可得 n=1时f(n+1)=1,n>1即n>=2时f(n+1)=2f(n)

dp4:最小花费爬楼梯
给定一个整数数组 cost ,其中 cost[i] 是从楼梯第i 个台阶向上爬需要支付的费用,下标从0开始。一旦你支付此费用,即可选择向上爬一个或者两个台阶。你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。请你计算并返回达到楼梯顶部的最低花费。

#递归超时版
def go(cost,start,hadcost):
    end=length-1
    if(start+1==end):
        return hadcost+cost[start]
    elif(start==end):
        return hadcost+cost[end]
    else:
        return min(go(cost,start+1,hadcost+cost[start]),go(cost,start+2,hadcost+cost[start]))
length=int(input())
cost=list(map(int,input().split()))
x=min(go(cost,0,0),go(cost,1,0))
print(x)

#for循环 dp超省时
slong=int(input())
s=input().split()
s=[int(i) for i in s]
dp=[0,0]
for i in range(2,slong+1):
    dp.append(min(dp[i-1]+s[i-1],dp[i-2]+s[i-2]))
print(dp[slong])

dp26:跳跃游戏(之前第二道华为机试题的变形)
给定一个非负整数数组 nums ,你最初位于数组的第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。

补充贪心思想+最大cover思想

#贪心:如果给定的数据长度较小,可以采用动态规划,设置 dp, dp[i] 表示 是否可以调到该位置;由于数据的长度较大,双重循环遍历会超时,采用贪心策略,从后向前遍历数组,看当前位置 + 值 是否 >= 给定的位置,最终判断是否为 0(这个思想要记住!!)
import sys
n = int(sys.stdin.readline().strip())
data = list(map(int, sys.stdin.readline().strip().split()))
start = n - 1
for i in range(n - 1, -1, -1):
    if i + data[i] >= start:
        start = i
    # 此处可对 i 进行判断是否为 0 跳出循环
if start == 0:
    print("true")
else:
    print("false")
#计算最大cover(这个思想要记住!!)
n=int(input())
n=n-1
str= [int(i) for i in input().split()]
#print(str)
cover=0
now=0
flag='false'
while now<n and cover<n:
    if(str[now]==0):
        if(cover<=now):
            break
        else:
            now+=1
    else:
        cover=max(cover,now+str[now])
        now+=1
    #print('now',now,'cover',cover)
if now>=n or cover>=n:
    flag='true'
print(flag)

gcd (greatest common divisor)

牛客华为机试题刷题笔记总结[103题更新完毕才收尾,建议关注收藏]_第3张图片
为什么是这个公式?试想倘若a和b都同时能整除一个数c,即c就是公约数,又有a mod b =r,展开可以得到a=cx1,b=cx2,a=bx3+r(均为整数),cx1=bx3+r=cx2x3+r =>c(x1-x2x3)=r,故c也可以被r整除,即gcd(a,b)转移成gcd(a mod b ,b)

你可能感兴趣的:(算法,面试,python)