跳过了部分习题。。。
习题4-2:此题不难,我采取最直接的办法,暴力遍历进行判断,代码如下:
def do_squares(h,v,n):
def test(i,j,l):
_i = i;_j = j
while(_j<j+l):
if(h[_i][_j]==0):return False
_j+=1
while(_i<i+l):
if(v[_i][_j]==0):return False
_i+=1
while(_j>j):
if(h[_i][_j-1]==0):return False
_j-=1
while(_i>i):
if(v[_i-1][_j]==0):return False
_i-=1
return True
count = [0]*(n-1)
for i in range(1,n-1):
for j in range(1,n-1):
for length in range(1,n-1):
if(test(i,j,length)):count[length]+=1
for k in range(1,n-1):
if(count[k]!=0):print('Number of suqare with length(%d) : %d'%(k,count[k]))
def squares(h,v,n):
H = [ [0]*(n+1) for i in range(n+1)]
V = [ [0]*(n+1) for j in range(n+1)]
for x in h:H[x[0]][x[1]] = 1
for y in v:V[y[0]][y[1]] = 1
do_squares(H,V,n+1)
squares([(1,1),(1,3),(2,1),(2,2),(2,3),(3,2),(4,2),(4,3)]
,[(1,1),(1,2),(2,2),(3,2),(2,3),(1,4),(2,4),(3,4)],4)
算法复杂度是O(n^4),有没有办法降低一下复杂度呢?仔细思考一下,可以构造一个数组用来存储点之间的互联情况,先从边长最大的正方形开始检验,这样可以把能够组成一条边的点信息记录下来,先检验是否已经连通,如果没有再采用遍历检验的办法.这样能避免很多多余的检验,但是增加了空间复杂度.
习题4-4:用python解决这个问题确实简单…..排序后比较就ok:
def Cube(a,b):
X = [[a[0],a[5]],[a[1],a[4]],[a[2],a[3]]]
Y = [[b[0],b[5]],[b[1],b[4]],[b[2],b[3]]]
for i in range(3):
X[i].sort();Y[i].sort()
X.sort();Y.sort()
print(X==Y)
Cube('grggrb','rggbgr')
习题4-5:IP地址求最大子网和子网掩码,没啥好说的,直接求解.
def convert(x):
ans = ''
tmp = x.split('.')
for each in tmp:
tmp_ans = bin(int(each))[2:]
ans += '0'*(8-len(tmp_ans))+tmp_ans
return ans
def recovert(y):
ans = ''
for i in range(0,32,8):
ans += str(int(y[i:i+8],base = 2))+'.'
return ans[:-1]
def solve(IP):
net = convert(IP[0])
for each_ip in IP[1:]:
tmp = convert(each_ip)
for i in range(len(net)):
if(tmp[i]!=net[i]):net = net[:i];break
mask = '1'*len(net)+'0'*(32-len(net))
net += '0'*(32-len(net))
print('%s*********************%s'%(recovert(net),recovert(mask)))
solve(['194.85.160.183','194.85.160.177','194.85.160.178'])
习题4-7:RAID技术,用校验码来恢复数据.本题也略烦。基本思路就是在几个进制之间不停的转换.主要是熟悉hex,int,bin几个方法
def do_raid(d,s,b,Type):
check_result = 0 if Type=='E' else 1
def eor(x,check_pos):
ans = 0
count = 0
err_pos = 0
for i,each in enumerate(x):
if(each!='?'):ans ^= int(each,base = 2)
else:count+=1;err_pos = i
if(count>1):return False,x
elif(count==1):
tmp = bin(ans^check_result)[2:]
x[err_pos] = '0'*(s-len(tmp))+tmp
return True,x[0:check_pos]+x[check_pos+1:]
check_pos = 0
final_ans = ''
for i in range(0,len(b),d):
if(b[check_pos]=='?'):print('check illegal');return
test,tmp = eor(b[i:i+d],check_pos%d)
if not test:print('too many error');return
check_pos += (d+1)
print(tmp)
final_ans += ''.join(tmp)
print(final_ans,hex(int(final_ans,2)))
do_raid(5,2,['00','01','10','11','?','01','10','11','10','?','01','11','01','10','?',
'11','10','?','11','01','11','11','11','00','11'],'E')
习题4-8,此题略有一点难度,主要注意3点,第一:在时间临界点的时候认为它是属于前面时间区域的,第二,在超过时间周期之后应该取余取回来,但是这样存在一个问题,取余之后得到的是0,但是实际上该是1,因为实际意义上从末端走了1格应该是走到1而不是0,当然还可以为了避免讨论边界情况我们统一把初始时间向前推0.5min(这是我的做法).最后注意什么情况下是没有解的?我采取的办法是当时刻表和最开始的时刻重复且此时没有全部清醒时返回-1.
def Tired_students(students):
n = len(students)
A = [students[i][0] for i in range(n)]
B = [students[i][1] for i in range(n)]
C = [students[i][2]-0.5 for i in range(n)]
print(A,B,C)
time = 1
sleeped = 0
initial_c = C[:]
tmp = [1]*n
for i in range(n):
if(C[i]>A[i]):sleeped += 1;tmp[i] = 0
print(sleeped,tmp)
while(sleeped !=0):
time += 1
tmp_sleeped = 0
for i,each in enumerate(C):
C[i] = (C[i]+1)%(A[i]+B[i])
if(C[i]>A[i]):
if(tmp[i] == 1):
if(2*sleeped > n):
tmp[i] = 0
tmp_sleeped += 1
else:
C[i] = 0
elif(tmp[i]==0):
tmp[i] = 1
tmp_sleeped -= 1
sleeped += tmp_sleeped
print('the %d分钟: '%time,tmp,sleeped,C)
if(initial_c == C and sleeped != 0):return -1
return time
习题4-10:给定一个m*n的网格,每个网格都有一定的高度,里面有一定体积的海水,网格周围是无限高的墙,求解海水的海拔.一种思路如下:首先对海拔进行排序,然后每次尝试一个新的海拔高度,如果发现海水的体积加上网格的体积小于整个长方体(网格)的体积就退出循环.否则继续试探。
然后假设在上一个临界高度之上还应该多出h’的高度,列出方程:v0+v1+h’(num - i) = 100*num(h+last_h),计算出last_h+h’就得到最后的高度.
def Flooded(m,n,h,v):
h.sort()
num = m*n
v0 = v
v1 = 0
tmp_h = 0
final_h = 0
count = 0
last_h = 0
i = 0
while(i<100):
if(h[i] != last_h):
if(v0+v1+(num - i)*(h[i]-last_h)*100 < h[i]*num*100 ):
final_h = last_h;break
else:
v1 += (num - i)*(h[i]-last_h)*100
last_h = h[i]
i += 1
x = num - i
print(final_h,(v0+v1-100*num*last_h)/(100*num-x*num)+last_h,i/num)