#开灯问题
def N_lamps(n,k):
L = [0]*(n+1)
for i in range(1,k+1):
factor = 1
while(factor*i<=n):
L[factor*i] = 1-L[factor*i]#1代表开
factor += 1
for k,i in enumerate (L):
if(i==1):print(k,' ',end = '')
###没啥好说的,简单的模拟
#蛇形矩阵
def snake_matrix(n):
L = [[0]*n for i in range(n)]
dir = [(1,0),(0,-1),(-1,0),(0,1)]
i = 0;j = n-1;x = 1;
L[i][j] = 1;#先初始化第一个位置
while(x<n*n):
while(i<n-1 and (L[i+1][j]==0)):
L[i+1][j] = x+1;x+=1;i+=1
while(j>0 and (L[i][j-1]==0)):
L[i][j-1] = x+1;x+=1;j-=1
while(i>0 and (L[i-1][j]==0)):
L[i-1][j] = x+1;x+=1;i-=1
while(j<n-1 and (L[i][j+1]==0)):
L[i][j+1] = x+1;x+=1;j+=1
for row in L:
print(row)
###本题有两种思路,但是一个是跟着填入的数字走,根据当前坐标判断下一个数字应填在哪里,另一种思路就是跟着轨迹走,下,左,上,右不断循环.第一种方法相对麻烦(我就采取的第一种~~~~),因此给出了第二种的python实现.
###竖式问题,给定一个数字集合,找出所有形如abc*de的竖式算式,并且保证完整的竖式所有数字都是属于该集合。输出所有的竖式和解的行数。代码如下:
number = 0
def vertical_form_de(abc,data):
def test(buf,data):
for each in buf:
if(int(each) not in data):return False
return True
global number
for d in data:
for e in data:
de = d*10+e
x = abc*d;y = abc*e;z = abc*de
buf = str(x)+str(y)+str(z)
if(test(buf,data)):
number+=1;
print('%5d\nX%4d\n-------\n%5d\n%4d\n------\n%5d\n'%(abc,de,x,y,z))
def vertical_form_abc(data):
for a in data:
for b in data:
for c in data:
vertical_form_de(a*100+b*10+c,data)
print('The number of solutions = %d'%number)
###书上给出的解法太暴力了,我的思路是从给定的集合里面来遍历.需要注意下输出格式,利用%5d,%4d来控制格式.
def toTex(buf):
left_right = 0#0代表左,1代表右
new_buf = ''
for each in buf:
if(each == '"'):
if(left_right == 0):each = '“'
else: each = '"'
left_right = 1 - left_right
new_buf+=each
print(new_buf)
#toTex('" To be or bot to be," quoth the Brad,"that is the question".')
#字符错位问题
####这题也很简单,关键是用好一个数组,一开始我想用map来解,但是这有些自找麻烦。。。。还是这个策略更容易实现.这也提醒我们使用map前要考虑有没有更简单的对应关系.
def WERTYU(buf):
s = '`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;ZXCVBNM,./'
for char in buf:
try:
pos = s.index(char)
except:
pos = -1
if(pos!=-1):print(s[pos-1],end = '')
else:print(char,end = '')
#WERTYU('O S, GOMR YPFSU/')
def palindromes(buf):
s = 'A 3 HIL JM O 2TUVWXY51SE Z 8 '
msg = ['is not a pal','is a regular pal','is a mirrored string','is a mirrored pal']
def rev(ch):
if(ch.isalpha()):return s[ord(ch)-ord('A')]
else :return s[ord(ch)-ord('0')+25]
print(buf,buf[::-1])
p = 1 if (buf[::-1]==buf) else 0#回文
old_buf = list(buf)
buf = list(map(rev,buf))
m = 1 if (buf[::-1]==old_buf) else 0
print(m,p,buf,old_buf)
print (msg[2*m+p])
#palindromes('NOTAPALINDROME')
#palindromes('2A3MEAS')
#palindromes('ATOYOTA')
###方法是采取一个数组来进行映射,注意几点:首先reverse会改变自己所绑定的值,因此较好的办法是采取[::-1]的切片,对于str和list都是通用的.另外四种情况的组合最后是采取一个类似二进制的表达来输出的.msg的作用很有意思.
def master_mind(ans,guess):
#test从guess本身考虑问题
def test(each):
tot = 0
wrong_occur = 0
mark = [0]*len(each)
for index in range(len(each)):
if(ans[index] == each[index]):tot+=1;mark[index]=1;
for index in range(0,len(each)):
if(mark[index]!=1):
pos = -1
while(True):
try:
pos = ans.index(each[index],pos+1)
if(mark[pos]!=1):wrong_occur += 1;break;
except:break
return tot,wrong_occur
#test1从1-9数字的角度考虑问题
def test1(each):
A = 0;B = 0;
for index in range(len(each)):
if(ans[index] == each[index]):A+=1;
for d in range(1,10):
c1 = 0;c2 = 0;
for index in range(len(each)):
if(ans[index]==d):c1+=1;
if(each[index]==d):c2+=1;
B += min(c1,c2);
return (A,B-A)
for each in guess:
print(test(each))
###其实这个问题书本上的解法很有意思,值得思考,我给出的解法需要多用一个数组作为标志数组,算法复杂度是O(n^2),首先求解出A并且做好标记,然后对guess序列的每一个数进行在ans中的查找,直到有一个位置的数字被找到且没有被标记过.
###而书本的答案则只需要O(n*m)的复杂度,其中m是代表可能出现的数字集合的长度.
###书本的答案采取的办法是统计每一个数字在ans和guess序列出现的次数,然后取两者中的最小值,这代表它们对B做出的贡献,然后不断累加即可.最后注意要减去A,因为不能计算已经正确包含的值.
def mysum(x):
sum = x
while(x>0):
sum += x%10
x //= 10
return sum
def min_generator(n):
m = len(str(n))#获取n的位数
for x in range(n-9*m,n):#n-9m -> n-1
if(mysum(x)==n):print(x);return
print(0)
#min_generator(121)
#mysum(5555)
def less(a,b):
a_l = len(a);b_l = len(b)
if(a_l > b_l): return less(b,a)
n = a_l if a_l < b_l else b_l
for i in range(n):
if(a[i]<b[i]):return True#小于
elif(a[i]>b[i]):return False#大于
if(b_l == a_l):return False#相等
else: return True#小于
###这个题目不难,但是书上给出的答案有点意思,居然是空间换时间的做法,这个角度值得思考.但是还是有其他办法的,可以很容易的缩小枚举的范围是n-9m到n,m是n的位数.
def circular_s(s):
temp = s
for i in range(len(s)):
if(less(temp,s)):ans = temp
temp = temp[1:]+temp[0]
print(ans)
#circular_s('CGAGTCAGCT')
def score(buf):#统计连续出现的O
curr_num = 0;tot = 0
for ch in buf:
if(ch=='O'):curr_num+=1;
else: curr_num = 0
tot += curr_num
print(tot)
#score('OOXXOXXOOO')
def Molar_Mass(buf):
weight = {'C':12.01,'H':1.008,'O':16.00,'N':14.01}
sum = 0.0;i = 0
length = len(buf)
while(i+1<length):
if (buf[i+1].isdigit()):sum += weight[buf[i]]*int(buf[i+1]);i+=2
else: sum += weight[buf[i]];i+=1;
if(i==length-1):sum+= weight[buf[i]]
print(sum)
#Molar_Mass('C6H5OH2')
###唯一需要注意的是最后一个分子
def get_zero(i,num):
tot = 0
u = 1;
for j in range(1,i+1):
x = j*u;
tot += x
u *= 10;
tot*=9
return tot - num*9
def digit_count(n):
k = 0;i = 0;
while(True):
if((k*10+9) <= n):k = k*10+9;i+=1;
else:break
gap = n - k
sum = [i*(k+1)//10]*10;
sum[0] = get_zero(i,sum[1])
for digit in range(k+1,n+1):
for ch in str(digit):
sum[ord(ch)-ord('0')]+=1
print(sum)
#digit_count(5000)
####这个题目暴力解就太简单了,这里稍微用了一点数学的知识:
####我们首先看一看1-999的出现情况,首先假设数字出现的规律是001-999,这样因为每一位都是平均分配的,所以每一位出现的次数是3*1000/10
= 300
def perodic(buf):
def test(s):
k = len(s)
for i in range(len(buf)//k):
if(s!=buf[i*k:(i+1)*k]): return False
return True
beg = '';end = ''
length = len(buf)
for i in range(length//2 + 1):
beg += buf[i]
end = buf[length-i-1]+end
if(beg == end and test(beg)):print(len(beg));return
print(len(buf))
#perodic('abccbaabccxba')
###这里的算法复杂度是n^2,先从两头开始比较,最坏情况下比较的次数是1+2+3+....(n/2) = n^2/8,然后进行检验,检验的比较次数是n.
###如果采取最直接的暴力比较法,最坏情况下的比较次数是(n/2)*n = n^2/2,显然上面的算法要好一些.但是还是不能降低复杂度的量级....
#空格迷题
def get_pos(matrix):
for i,k in enumerate(matrix):
for j,item in enumerate(k):
if(item == ' '):return[i,j]
def Puzzle(matrix,command):
empty_pos = get_pos(matrix)
dir = {'A':[-1,0],'B':[1,0],'L':[0,-1],'R':[0,1]}
def move(instruction):
nonlocal empty_pos#声明它不是move的局部变量
old_i = empty_pos[0]
old_j = empty_pos[1]
if(instruction not in dir):return False
i = old_i + dir[instruction][0]
j = old_j + dir[instruction][1]
if(i<5 and i >0 and j<5 and j>0 ):
matrix[old_i][old_j],matrix[i][j] = matrix[i][j],matrix[old_i][old_j]#交换两个元素
empty_pos = [i,j]
return True
else:return False
for ins in command:
if(not move(ins)):print('This puzzle has no final configuration');return
for i in matrix:
print(i)
A = [['T','R','G','S','J'],['X','D','O','K','I'],['M',' ','V','L','N'],['W','P','A','B','E'],['U','Q','H','C','F']]
Puzzle(A,'ARR')
算法竞赛入门经典第三章总结(python实现)
最新推荐文章于 2024-07-05 20:35:50 发布